4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
1

Создание простого контроллера от третьего лица ( для RPG игры)

17.01.2018, 19:28. Показов 16591. Ответов 21

Всем привет, недавно появилось желания написать небольшую РПГ игру, точнее базу для нее ( лишь скрипты и механизм взаимодействия без моделей).
Сейчас задача стоит такая:
1) Создать контроллер от третьего лица. То есть есть MouseOrbit по другому + коллизия в зависимости от стен/препятствий.
И движение самого персонажа через WASD + Space.
В идеале хотелось бы так:
-Вращение камеры происходит как по X , так и по Y ( Mouse X, Mouse Y), А вот движение самого игрока только вдоль оси Y. При этом на одно и ту же величину, если как-то можно ее сгладить - то вообще супер, чтобы не было резких рывков.
Тут же стоит вопрос - как сделать самого Player Объект? То есть иерархию родителей и дочерних объектов.
Где-то видел такое и с тех пор так делаю: Создается пустой GameObject - называется Player( Родитель для всех следующих объектов). Дальше создается три дочерних объекта внутри Player.
1) PlayerModel( Модель персонажа будущая) - на ней нет компонентов вообще, кроме Mesh Render и Mesh Filter вроде бы.
2) Eyes ( Камера которая стоит, допустим, на половине роста персонажа - это сейчас не так важно, так как в скрипте она перемещается на другое расстояние и начальное значение роли не играет).
3) CameraTarget ( Цель для камеры, на которую смотрит камера, ставим там где выгодно, то есть по ситуации, как удобнее) - Это пустой GameObject всего с одним компонентом Transform.

Вот какая сейчас иерархия у меня стоит)

Теперь главное, сам скрипт: Я его вешаю на Родительский объект Player, так же коллайдер боксовкий ставлю и Rigidbody( В принципе потом заменить можно на CharachterController).
Вот сам скрипт:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class ThirdPersonController : MonoBehaviour {
 
    //Mouse Settings
    public float distanceToTarget=2.0f;
    public Transform cam;
    public Transform target;
    private float xRot;
    private float yRot;
    public float rotationSmoothTime=0.12f;
    Vector3 rotationSmoothVelocity;
    Vector3 currentRotation;
    public float ms=10.0f;
    public Vector2 maximum = new Vector2 (-40, 85);
    //Jump and Movement
    public float PlayerSpeed = 5.0f;
    public float PlayerJumpForce=800.0f;
    private Rigidbody PlayerRB;
    private bool isGrounded;
 
    // Use this for initialization
    void Start () {
 
        PlayerRB = GetComponent<Rigidbody> ();
 
        if (PlayerRB.velocity.y == 0)
            isGrounded = true;
        else
            isGrounded = false;
    }
 
    // Update is called once per frame
    void Update () {
 
        //Mouse Look
 
        yRot += Input.GetAxis ("Mouse X") * ms;
        xRot -= Input.GetAxis ("Mouse Y") * ms;
        xRot = Mathf.Clamp (xRot, maximum.x, maximum.y);
 
        currentRotation = Vector3.SmoothDamp (currentRotation, new Vector3 (xRot, yRot), ref rotationSmoothVelocity, rotationSmoothTime);
 
        cam.transform.eulerAngles = currentRotation;
 
        RaycastHit hit;
        Ray ray = new Ray (cam.transform.position,cam.transform.forward);
 
        if(Physics.Raycast(ray,out hit,distanceToTarget)){
            if(hit.collider.tag == "Wall")
            {
                cam.position = target.position - cam.forward * distanceToTarget;  // Тут пока что и ниже в else стоит одинаковый cam.position - так как я не смог найти нужные координаты для перемещения коллизии вдоль ( внутри комнаты) стены. Ниже я проблему опишу,  а тут пока загадка какие координаты задать. 
                Debug.DrawRay (cam.transform.position,cam.transform.forward, Color.blue);
                Debug.Log (hit.point);
            }
            else 
                cam.position = target.position - cam.forward * distanceToTarget;
        }
 
 
 
    
 
 
        //Movement
        transform.Translate (Input.GetAxis ("Horizontal") * PlayerSpeed * Time.deltaTime, 0.0f, Input.GetAxis ("Vertical") * PlayerSpeed * Time.deltaTime);
 
 
        //transform.Rotate (0.0f, Input.GetAxis ("Mouse X") * ms, 0.0f); Тут главный вопрос - у меня выше камера вращается уже при помощи смены ее cam.transform.eulerAngels и тут же я вращаю весь объект на котором весит этот скрипт, то есть я камеру ( так как она дочерняя) тоже вращаю этой строкой? Тут идея как раз таки работала и камера вращалась и игрок сам вращался, но мне тут кажется при моей иерархии проблемы какие-то есть не заметные глазу, как будто несколько раз камера прокручивается, никто не подскажет? 
    
        //Jumping
 
        if (PlayerRB.velocity.y == 0)
            isGrounded = true;
        else
            isGrounded = false;
 
        if (Input.GetKeyDown(KeyCode.Space) && isGrounded) {
            PlayerRB.AddForce (transform.up * PlayerJumpForce*25, ForceMode.Force);
        }
    }
}
В общем, мне кажется,что следует как-то изменить скрипт, что бы весь Player( Родитель) вращался в зависимости от Input.GetAxis("Mouse X"), а камера только от Input.GetAxis("Mouse Y")
Тогда ведь не будет проблем с поворотом и не будет " Нескольких поворотов" Для камеры)

Но как реализовать это пока - не знаю. Если получится, то нужно как-то сгладить это дело для плавного поворота - но это уже после.

2) Задача № 2: Реализовать коллизию камеры и объектов с тэгами.

Суть такая - ведь камера находится на расстояния от игрока? По этому она пролетает сквозь стены и другие объекты - и, как следствие, персонажа не видно, стена мешает). В этом ситуации камера должна приближаться к игроку, как бы внутри комнаты, помещения, вдоль стены ездить. Для этого пользоваться нужно рэйкастом?
Я попробовал- создал луч из камеры прямо ( Выше в скрипте есть) на расстояние равное расстоянию от камеры до CameraTarget - навсякий случай дебагнул его для получение координат и рисования луча. Так вот, камера находится снаружи стены и луч попадает во внешнюю часть стену и hit.point ( координаты столкновения) снаружи получаются, а мне нужно как бы координаты внутри комнаты, прям которые за спиной игрока. Это основная проблема с коллизией, я так-то понял как сделать, но вот как получить нужно координаты - не знаю...
Вот скриншот для объяснения:
Создание простого контроллера от третьего лица ( для RPG игры)


Точка 1 - желаемое место, куда камера должна сместиться(внутри стены, вдоль неё как бы), а точка 2 - это как раз где сейчас луч сталкивается: hit.point - то есть не подходит мне. В общем мне нужно, что бы камера сместилась на точку 1, сейчас она пока что не смещается никуда, так как не знаю как поступить тут.

Файл с проектом прикреплю сюда и выложу на drive.google :
3D_Action_RPG_For_CyberForum.ru.rar
Ссылка:https://drive.google.com/open?... SskvULIJKj
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.01.2018, 19:28
Ответы с готовыми решениями:

Классы для RPG игры. 3 Части
Ребят помогите решить задачку) Часть 1 Создать класс «персонаж ролевой игры». Включить в...

Работа с классами для RPG игры
Всем доброе время суток о великие гении программирования. Возникла интересная мысль написать...

Задано местоимение третьего лица единственного числа. Составить алгоритм для определения его рода
Задано местоимение третьего лица единственного числа. Составить алгоритм для определения его рода....

Посоветуйте хороший 3Д игровой движок для создания игры с элементами RPG
Здравствуйте! Какой хороший игровой движок можете посоветовать. То есть движок, на котором...

21
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
18.01.2018, 11:13  [ТС] 2
Ночью пытался переделать всё немного, чтобы упростить понимание моей ситуации - создал новый проект и там накидал два скрипта: один повесил на персонажа Movement.cs, Другой на камеру MouseOrbit.cs;

В общем пока что можно только побегать/прыгать и вращать мышкой.

Пытался я сделать всё эту коллизию камеры... Сначала бросал луч из камеры в цель для камеры(Target). Потом понял, что нужно вроде как наоборот делать - Вроде бы уже получилось что-то похожее, но были подёргивания при столкновении луча и стены - постоянные рывки туда сюда камеры.
Пока что в коде нет коллизии камеры. Может кто-то для моего скрипта подсказать как решить проблему с коллизией камеры при помощи пускания луча?

Я пробовал так ( может кто глянуть его работу, а то на словах не объяснить): Вот проект сам и ссылка на него:CameraTest.rar
https://drive.google.com/open?... Nhbam3aDH7
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
20.01.2018, 21:44  [ТС] 3
Небольшой апдейт вопроса) Пока тут никто не отвечал - я уже почти разобрался с тем , что хочу получить в итоге. И почти сделал, только имеется небольшой баг ( косяк). Собственно вот проект сам:test.rar

Проблема в том, что при ходьбе влево/вправо персонаж нормально двигается и поворачивается, но при ходьбе вперёд/назад:

Он в зависимости от того, куда смотрит камера двигается еще и в по оси Y.

Я знаю в чём проблема, но как решить не понимаю: в скрипте я получаю координаты камеры и в зависимости от них двигаю персонажа в нужном направлении, только ось Х постоянна для камеры( так вращение происходит только в двух осях, а третья не используется). А вот ось Z Смещается при перемещение мышки вверх вниз, собственно тут он берет вектор куда смотрит ось Z камеры и в ту сторону ее двигает, меня все устроило бы, только чтобы персонаж двигался вдоль земли, как бы направление мне только нужно вдоль земли)


Примерно такой смысл:
Создание простого контроллера от третьего лица ( для RPG игры)


Синий Вектор( Ось Z ) Он будет двигаться в этом направлении. А мне нужен такой же вектор только вдоль земли, как бы чтобы движение было ограничено по Y. Не знаю как еще объяснить, но самом проекте понятно всё. Вообщем вперед-назад должно работать как влево-вправо) Заранее спасибо, жду ответов, а то пусто тут у меня :/
0
159 / 158 / 59
Регистрация: 19.02.2015
Сообщений: 821
20.01.2018, 22:07 4
Цитата Сообщение от Abomination_25 Посмотреть сообщение
А мне нужен такой же вектор только вдоль земли
Когда перемещаешь, бери из вектора камеры только X и Z координаты, а Y оставляй свой.
Т.е. что-то типо
C#
1
Vector3(cam.transform.position.x, transform.position.y, cam.transform.position.z)
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
20.01.2018, 23:13  [ТС] 5
А вы случайно не смотрели мой код конкретно? У меня просто поворот производиться за счёт Quaternion.LookRotation(); То есть мне вектор направления нужен, по Х он совпадает, а вот по оси Z происходит смещение... Которое никак не найти мне)

Добавлено через 21 минуту
Тут я поправил свой код - теперь работает! Но, почему - не знаю... По идее надо как-то просто реализовать этот код... А тут такие запарки с поворотом. Ведь всё должно быть просто и главное логично, у меня такое ощущение, что мой код работает не логично, будто это будет в последующем усложнять разработку и различные проверки... Есть у кого идеи как легче можно реализовать этот код?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Move : MonoBehaviour {
 
    public Transform cam;
 
    public float speed=7.5f;
 
    float gravity = -9.8f;
 
    public float rotSpeed = 25f;
 
    private CharacterController _controller;
 
    private Vector3 movement = Vector3.zero;
 
    // Use this for initialization
    void Start () {
        _controller = GetComponent<CharacterController> ();
    }
    
    // Update is called once per frame
    void Update () {
 
            float x = Input.GetAxis ("Horizontal");
            float z = Input.GetAxis ("Vertical");
 
            if (x != 0 || z != 0) {
                movement.x = x;
                movement.z = z;
            } else
                movement = Vector3.zero;
 
            if (Input.GetKeyDown (KeyCode.Space)) {
                movement.y = 20.0f;
            }
 
            if (movement != Vector3.zero)
                RotatePlayer ();
        
 
            _controller.Move (movement * Time.deltaTime * speed);
        
    }
 
    private void RotatePlayer(){
 
        movement = cam.TransformDirection (movement);
 
        Quaternion desiredRotation = Quaternion.LookRotation(movement);
 
        Quaternion temp = Quaternion.Euler (0.0f, desiredRotation.eulerAngles.y, 0.0f);
 
        transform.rotation = Quaternion.Slerp (transform.rotation,temp, Time.deltaTime * rotSpeed);
 
    }
}
Добавлено через 57 секунд
Вот бы разобраться с этим уже... Самое главное понять, как это получилось)

Добавлено через 19 минут
Ой, вот исправленный скрипт:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Move : MonoBehaviour {
 
    public Transform cam;
 
    public float speed=7.5f;
 
 
    public float rotSpeed = 25f;
 
    private CharacterController _controller;
 
    private Vector3 movement = Vector3.zero;
 
    // Use this for initialization
    void Start () {
        _controller = GetComponent<CharacterController> ();
    }
    
    // Update is called once per frame
    void Update () {
 
            float x = Input.GetAxis ("Horizontal");
            float z = Input.GetAxis ("Vertical");
 
            if (x != 0 || z != 0) {
                movement.x = x;
                movement.z = z;
            } else
                movement = Vector3.zero;
 
 
            if (movement != Vector3.zero)
                RotatePlayer ();
 
        movement.y=0;
 
            _controller.Move (movement * Time.deltaTime * speed);
        
    }
 
    private void RotatePlayer(){
 
        movement = cam.TransformDirection (movement.x,0.0f,movement.z);
 
        Quaternion desiredRotation = Quaternion.LookRotation(movement);
 
        Quaternion temp = Quaternion.Euler (0.0f, desiredRotation.eulerAngles.y, 0.0f);
 
        transform.rotation = Quaternion.Slerp (transform.rotation,temp, Time.deltaTime * rotSpeed);
 
    }
}
0
159 / 158 / 59
Регистрация: 19.02.2015
Сообщений: 821
21.01.2018, 09:05 6
Можно еще просто поворачивать игрока так же как и камеру (но только по Y)

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    public float speed = 6.0f;
    public float gravity = -9.8f;
    private CharacterController _charController;
 
    private float yRot;
    public float ms = 2.0f;
 
    void Start()
    {
        _charController = GetComponent<CharacterController>();
    }
    void Update()
    {
        float deltaX = Input.GetAxis("Horizontal") * speed;
        float deltaZ = Input.GetAxis("Vertical") * speed;
        Vector3 movement = new Vector3(deltaX, 0, deltaZ);
        movement = Vector3.ClampMagnitude(movement, speed);
        movement.y = gravity;
        movement *= Time.deltaTime;
        movement = transform.TransformDirection(movement);
 
        yRot += Input.GetAxis("Mouse X") * ms;
        transform.rotation = Quaternion.Euler(0f, yRot, 0.0f);
 
        _charController.Move(movement);
    }
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
21.01.2018, 15:43  [ТС] 7
Я такое проворачивал уже, спасибо за код, но я пытаюсь добиться немного другого результата. Можете я попробую вам получше свой идею объяснить?

Пока персонаж не двигается - камера облетает его (Orbit Camera) и сам персонаж не поворачивается никуда.
Как только были нажаты кнопки W/A/S/D персонаж поворачивается соответственно в нужном направлении и бежит туда, но поворот должен быть относительно положения камеры, То есть я смотрю допустим на персонажа спереди и жму вперед ( W)
тогда он поворачивается в ту сторону куда смотрит камера и движется туда. Так же и для других кнопок. У меня в проекте это реализовано, но довольно сложно и неправильно с точки зрения кода, так как я до сих пор там не вычислил нужный вектор... Примером такого управления может послужить игру Cube World. Или допустим вот видео, но там сложно они делают:https://www.youtube.com/watch?v=sNmeK3qK7oA В начале видео показано как всё работает это
0
159 / 158 / 59
Регистрация: 19.02.2015
Сообщений: 821
21.01.2018, 16:32 8
Цитата Сообщение от Abomination_25 Посмотреть сообщение
Или допустим вот видео, но там сложно они делают
Ну, честно говоря, не знаю, как сделать проще, чем у них)
Это нужно хорошо знать Quaternion'ы, Vector'а... С этим у меня проблемы))

Может проще взять уже готовое решение? (которое на видео используют)
Создание простого контроллера от третьего лица ( для RPG игры)
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
21.01.2018, 23:39  [ТС] 9
Уже попробовал, видимо пока так буду) Ну главное, что вы меня поняли, вроде бы у них не трудно почти, я даже почти понял) Ладно спасибо все равно, когда доделаю свой контроллер, если кому-то нужно могу выложить)

Добавлено через 6 часов 11 минут
Небольшой ап темы: Теперь когда уже большая часть вопроса решена, появилась проблема с тем, что стандартная переменная _controller.isGrounded иногда дает сбои на ровном месте, то есть вверх-вниз происхоид на 0.0000001 какие-то доли смещение. Как это можно поправить? И не подскажет кто-нибудь, как логичнее сделать анимацию падения, то есть от каких факторов ее включать? Через bool или float?
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
23.01.2018, 10:23  [ТС] 10
Кто-нибудь знает как решить проблему? Персонаж постоянно немного двигается верх вниз, и переменная _controller.isGrounded() так же постоянно меняется, а мне эта переменная нужна для анимации прыжка и падения. И у меня все время анимации меняются, так как переменная туда сюда меняет свое значение. Ап темы
0
159 / 158 / 59
Регистрация: 19.02.2015
Сообщений: 821
23.01.2018, 12:37 11
Цитата Сообщение от Abomination_25 Посмотреть сообщение
Персонаж постоянно немного двигается верх вниз
для начала бы выяснить, в связи с чем это происходит?
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
23.01.2018, 18:33  [ТС] 12
Вам привести примеры моих скриптов? У меня вроде бы все время есть притяжение к земле
0
159 / 158 / 59
Регистрация: 19.02.2015
Сообщений: 821
23.01.2018, 18:35 13
Цитата Сообщение от Abomination_25 Посмотреть сообщение
У меня вроде бы все время есть притяжение к земле
Как персонаж двигается?
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
23.01.2018, 18:40  [ТС] 14
Через функцию Character controller Move() при этом на него всегда действует гравитация veloxityY-=gravity*Time.Deltatime

Добавлено через 2 минуты
Вот мой проект на github: http:// github.com/alicewithalex/unity

Добавлено через 18 секунд
Называется SimpleRPG
0
159 / 158 / 59
Регистрация: 19.02.2015
Сообщений: 821
23.01.2018, 20:01 15
Abomination_25, в апдейте добавил Debug.Log(_controller.isGrounded);

Перс стабильно стоит на земле. Сколько бы я не перемещался. false выводит только вначале уровня и когда прыгаешь или падаешь.

Скорее всего анимацию нужно нормально настроить. Не нашел, где там включается анимация прыжка? Только удар вижу.
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
23.01.2018, 20:05  [ТС] 16
Просто сейчас конкретно я отключил это, может я соберу проект по новой и попробуете снова его скачать? Буду благодарен) через пол часа где то
0
159 / 158 / 59
Регистрация: 19.02.2015
Сообщений: 821
23.01.2018, 20:13 17
Цитата Сообщение от Abomination_25 Посмотреть сообщение
через пол часа где то
Будет время - посмотрю) Точно не через полчаса. Может кто другой успеет)
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
23.01.2018, 20:15  [ТС] 18
Хорошо, а вы спокойно смогли скачать исходники с github? Просто на будущее хотелось бы знать - можно ли свою ссылку давать) Вроде сейчас поставил проверку - даже работает) Разобрался вроде . Теперь занимаюсь БСП генерацией уровня)
0
159 / 158 / 59
Регистрация: 19.02.2015
Сообщений: 821
23.01.2018, 20:17 19
Abomination_25, Да. Только там в ссылке пробел лишний.
0
4 / 4 / 0
Регистрация: 13.12.2016
Сообщений: 246
23.01.2018, 21:21  [ТС] 20
Хорошо, спасибо) Теперь разобрался с базой для движения, пока что надо думать как генератор уровня сделать... Почитал про Binary Space Partitioning - так как показался более-менее простым, но увы не понимаю как его перенести на С#. Сам смысл алгоритма я понял, но не могу понять как организовать код именно в Unity
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.01.2018, 21:21

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Посоветуйте игры от лица женского персонажа для ПК
Хотелось бы что-то типа байонетты или т.п. Но байонетта только приставочная, мб есть что-то такое...

Прицеливание от третьего лица
Подскажите, как сделать нормальное прицеливание от третьего лица, подобно всем TPS, то есть при...

Камера у персонажа от третьего лица
Начал делать так, чтобы если ты играешь за персонажа от третьего лица, то ты мог поворачивать...

Стрельба из лука от третьего лица
всем привет делаю &quot;мморпг космических масштабов&quot; (шутка) от третьего лица.... хочу реализовать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.