Форум программистов, компьютерный форум, киберфорум
Unity, Unity3D
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/15: Рейтинг темы: голосов - 15, средняя оценка - 4.87
891 / 161 / 84
Регистрация: 30.07.2022
Сообщений: 1,386
Записей в блоге: 4
1

Реализовать перемещение персонажа

11.09.2022, 23:24. Показов 2811. Ответов 9

Author24 — интернет-сервис помощи студентам
Доброго времени!
Столкнулся с проблемой(прокрастинацией в коде!).
Пытаюсь реализовать перемещение персонажа и для разного типа перемещения использовать разную скорость.
Выглядит это примерно так.

if(Shift) скорость бега
else
if(Ctrl) скорость на корточках
else
if(Water) скорость плавания
else
скорость ходьбы

Я знаю о существовании паттернов программирования. Хотя и не понимаю с чем их едят. С помощью пространных пояснений от разных авторов понял, что мне надо что то вроде этих паттернов чтобы избавиться от ИФОВ.
Простое загугливание паттернов даёт слишком абстрактные знания. Или наоборот слишком частные случаи.
Вообще не понятно как их учить.
И какой выбрать для моего случая.

Буду рад любым советам.
Заранее спасибо!
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.09.2022, 23:24
Ответы с готовыми решениями:

Перемещение персонажа
При перемещении персонажа вправо, перемещение происходит плавное. При перемещении персонажа влево,...

Перемещение персонажа
При нажатие кнопок w или s персонаж двигается правильно(вперед или назад), но при нажатии a или d...

Перемещение персонажа
Здравствуйте. У меня есть объект, который движется из точки А в точке Б. Между этими точками(А, Б)...

Непрерывное перемещение персонажа по Button UI
Здравствуйте, подскажите, пожалуйста, как сделать непрерывное перемещение персонажа пока нажата...

9
52 / 35 / 16
Регистрация: 03.08.2019
Сообщений: 389
12.09.2022, 11:48 2
персонаж постоянно в движении или движение происходит при нажатии на кнопки?
0
891 / 161 / 84
Регистрация: 30.07.2022
Сообщений: 1,386
Записей в блоге: 4
12.09.2022, 12:10  [ТС] 3
Fantom1987, при нажатии на кнопки. WASD + Mouse.

возможно мне подойдет паттерн состояния для переключения скорости.
Я нашел видео и понял как они создаются.
Но в конце автор показал дулю! Управляя переключениями между состояниями простыми if =(
0
52 / 35 / 16
Регистрация: 03.08.2019
Сообщений: 389
12.09.2022, 12:45 4
devillived, не понимаю зачем так заморачиваться... делайте так чтобы сами понимали, что написали. чем проще код тем лучше - имхо)
0
891 / 161 / 84
Регистрация: 30.07.2022
Сообщений: 1,386
Записей в блоге: 4
12.09.2022, 12:55  [ТС] 5
Fantom1987, проблема в том, что проще не работает.
и если я захочу добавить бег на корточках например. мне прийдется ТАКОЕ городить!!!
вот я и ищу способ простой реализации ветвления условий с возможностью расширения.
0
52 / 35 / 16
Регистрация: 03.08.2019
Сообщений: 389
12.09.2022, 13:13 6
писал под 2д, но возможно поможет в реализации
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
private bool ButtonLeft;
private bool ButtonRight;
private bool ButtonUp;
private bool ButtonDown;
 
private int Direction; // <4 8^ 6> 2v
private float MoveSpeed = 2;
 
void GetInput()
    {
        ButtonLeft = Input.GetKey(KeyCode.LeftArrow) && !Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.UpArrow) && !Input.GetKey(KeyCode.DownArrow);
        ButtonRight = !Input.GetKey(KeyCode.LeftArrow) && Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.UpArrow) && !Input.GetKey(KeyCode.DownArrow);
        ButtonUp = !Input.GetKey(KeyCode.LeftArrow) && !Input.GetKey(KeyCode.RightArrow) && Input.GetKey(KeyCode.UpArrow) && !Input.GetKey(KeyCode.DownArrow);
        ButtonDown = !Input.GetKey(KeyCode.LeftArrow) && !Input.GetKey(KeyCode.RightArrow) && !Input.GetKey(KeyCode.UpArrow) && Input.GetKey(KeyCode.DownArrow);
    }
 
    void GetDirection()
    {
        if (ButtonLeft) Direction = 4;
        if (ButtonRight) Direction = 6;
        if (ButtonUp) Direction = 8;
        if (ButtonDown) Direction = 2;
    }
private void Move()
    {
        switch (Direction)
        {
            case 2:
                transform.position = new Vector2(transform.position.x, transform.position.y - MoveSpeed * Time.deltaTime);
                break;
            case 4:
                transform.position = new Vector2(transform.position.x - MoveSpeed * Time.deltaTime, transform.position.y);
                break;
            case 6:
                transform.position = new Vector2(transform.position.x + MoveSpeed * Time.deltaTime, transform.position.y);
                break;
            case 8:
                transform.position = new Vector2(transform.position.x, transform.position.y + MoveSpeed * Time.deltaTime);
                break;
        }
    }
0
891 / 161 / 84
Регистрация: 30.07.2022
Сообщений: 1,386
Записей в блоге: 4
12.09.2022, 13:35  [ТС] 7
Fantom1987, Спасибо!
Я знаком с данной конструкцией.
Это по сути те же ифы, то лько завернутые в switch case.

Ну ладно пойду дальше книги по Unity читать. может там что то будет.

Всем спасибо! Всем удачи.
0
2636 / 1564 / 853
Регистрация: 23.02.2019
Сообщений: 3,876
12.09.2022, 21:56 8
Лучший ответ Сообщение было отмечено devillived как решение

Решение

Цитата Сообщение от devillived Посмотреть сообщение
и если я захочу добавить бег на корточках например. мне придется ТАКОЕ городить!!!
вот я и ищу способ простой реализации ветвления условий с возможностью расширения.
Тема конечно непростая и в двух словах объяснить сложно. Если попробовать использовать такую "машину состояний", то кода придётся писать много, но зато легче понимать происходящее, так как каждое состояние описано в отдельном, конкретном классе и сразу видно - что оно делает (это состояние). Но совсем не факт, что вам в итоге будет удобно пользоваться этим способом.

Допустим в следующем примере есть игрок. В Update этого игрока выполняется update его текущего состояния. То-есть состояния могут быть разные, и каждое описывает своё, конкретное поведение. Каждое состояние имеет ссылку на игрока, чтобы была возможно ему что-то сообщить, например дать команду "изменить состояние" или что-то другое.

Здесь у игрока 4 состояния (покой, ходьба, бег, плавание), изначально устанавливается состояния покоя.
- состояние покоя ловит нажатие клавиш движения, и если движение есть, то переходит в состояние ходьбы

- состояние ходьбы тоже ловит клавиши и двигает игрока, но если нажимается клавиша шифт, то переходит в состояние бега

- состояние бега так же ловит клавиши и увеличивает скорость игрока, а так же дополнительно крутит его, как только клавиши движения отжаты или отжат шифт, то состояние переходит в состояние ходьбы

- сам игрок (вне зависимости от состояния) ловит нахождения в триггере воды. И если попадает в него, то меняет своё состояние на состояние плавания. В котором добавляется возможность плавать не только влево-вправо, но и вверх-вниз.

Для наглядности добавлена смена цвета у игрока и надпись на ним с описанием текущего состояния

Реализовать перемещение персонажа


Сам код всего этого "добра" выглядит пугающе, но это потому что он сделан для примера, плюс всё в одном файле.

Кликните здесь для просмотра всего текста
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
 
public class Player : MonoBehaviour
{
    private IPlayerState _myState;
    private Dictionary<Type, IPlayerState> _states;
 
    private void Start()
    {
        _states = new Dictionary<Type, IPlayerState>();
        _states.Add(typeof(IdleState), new IdleState(this));
        _states.Add(typeof(WalkState), new WalkState(this));
        _states.Add(typeof(RunState), new RunState(this));
        _states.Add(typeof(SwimState), new SwimState(this));
 
        SetState<IdleState>();
    }
 
    private void Update()
    {
        _myState.Update();
    }
 
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag("Water"))
            SetState<SwimState>();
    }
 
    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.CompareTag("Water"))
            SetState<IdleState>();
    }
 
    private void OnDrawGizmos()
    {
        UnityEditor.Handles.Label(transform.position + Vector3.up, _myState?.ToString());
    }
 
    public void SetSpriteColor(Color color)
    {
        GetComponent<SpriteRenderer>().color = color;
    }
 
    public void SetState<T>() where T : IPlayerState
    {
        Type targetState = typeof(T);
 
        if (_states.ContainsKey(targetState))
        {
 
            _myState?.EndState();
 
            _myState = _states[targetState];
            _myState.BeginState();
        }
    }
}
 
public interface IPlayerState
{
    void BeginState();
    void EndState();
    void Update();
}
 
public class IdleState : IPlayerState
{
    public readonly Player Player;
 
    public IdleState(Player player)
    {
        Player = player;
    }
 
    public void BeginState()
    {
        Player.SetSpriteColor(Color.grey);
    }
 
    public void EndState()
    {
        // empty
    }
 
    public void Update()
    {
        if (Input.GetAxis("Horizontal") != 0)
            Player.SetState<WalkState>();
    }
}
 
public class WalkState : IPlayerState
{
    public readonly Player Player;
    public float WalkSpeed = 1f;
 
    public WalkState(Player player)
    {
        Player = player;
    }
 
    public void BeginState()
    {
        Player.SetSpriteColor(Color.green);
    }
 
    public void EndState()
    {
        // empty
    }
 
    public void Update()
    {
        float moving = Input.GetAxis("Horizontal");
 
        if (moving == 0)
            Player.SetState<IdleState>();
 
        if (moving != 0 && Input.GetKey(KeyCode.LeftShift))
        {
            Player.SetState<RunState>();
            return;
        }
 
        Player.transform.Translate(Vector2.right * moving * WalkSpeed * Time.deltaTime);
    }
}
 
public class RunState : IPlayerState
{
    public readonly Player Player;
    public float RunSpeed = 5;
    public RunState(Player player)
    {
        Player = player;
    }
 
    public void BeginState()
    {
        Player.SetSpriteColor(Color.red);
    }
 
    public void EndState()
    {
        Player.transform.rotation = Quaternion.identity;
    }
 
    public void Update()
    {
        float moving = Input.GetAxis("Horizontal");
 
        if (Input.GetKey(KeyCode.LeftShift) == false || moving == 0)
        {
            Player.SetState<WalkState>();
            return;
        }
 
        Player.transform.Translate(Vector2.right * moving * RunSpeed * Time.deltaTime, Space.World);
        Player.transform.Rotate(Vector3.forward, moving * -RunSpeed, Space.Self);
    }
}
 
public class SwimState : IPlayerState
{
    public readonly Player Player;
    public float SwimSpeed = 0.5f;
    public SwimState(Player player)
    {
        Player = player;
    }
 
    public void BeginState()
    {
        Player.SetSpriteColor(Color.cyan);
    }
 
    public void EndState()
    {
        // empty
    }
 
    public void Update()
    {
        float movingX = Input.GetAxis("Horizontal");
        float movingY = Input.GetAxis("Vertical");
 
        Player.transform.Translate(new Vector2(movingX, movingY) * SwimSpeed * Time.deltaTime);
    }
}


Ни в коем случае не принимайте это как панацею. Здесь лишь просто попытка объяснить мои понимания данного вопроса. Всё может выглядеть совершенно иначе, правильнее и гибче. Всё нужно подстраивать под свои конкретные задачи.

На всякий случай добавлю пакет со сценой, но не уверен, что он корректно экспортировался.
StatesExamplePackage.zip
1
891 / 161 / 84
Регистрация: 30.07.2022
Сообщений: 1,386
Записей в блоге: 4
12.09.2022, 22:18  [ТС] 9
samana, Восхитительно!
Спасибо большое!


Удивительно! я понимаю, что там написано. Вы все классно написали!
0
2636 / 1564 / 853
Регистрация: 23.02.2019
Сообщений: 3,876
12.09.2022, 22:36 10
Цитата Сообщение от devillived Посмотреть сообщение
Удивительно! я понимаю, что там написано.
devillived, Благодарю. Честно говоря удивлён, что код оказался понятным со стороны.
0
12.09.2022, 22:36
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.09.2022, 22:36
Помогаю со студенческими работами здесь

Перемещение персонажа по средствам анимации
Доброго времени суток. Создал персонажа и анимацию с помощью mixamo. Как настроить анимацию так...

Перемещение персонажа через наклона устройства
Здравствуйте. Такой вопрос. Как заставить юнити перемещать игровой объект, к примеру шар, при...

Задать перемещение персонажа по клику мыши
Есть 2д тайлмап, на ней нужно задать перемещение персонажа по клику мыши. Т.е. перс должен идти к...

Перемещение объектов || или создание персонажа
Здравствуйте, я начинающий разраб по юньке и мне очень понравилась механика перемещения в игре...

Возможно ли реализовать создание персонажа самим игроком?
Юнити 2Д. Ну когда чел заходит в игру, была бы кнопка типа создать персонажа, а потом он может...

Не могу реализовать движение персонажа по заданной кривой из точек
Всем здравствуйте, столкнулся с такой проблемой, персонаж должен двигаться по заданной...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru