Форум программистов, компьютерный форум, киберфорум
Unity, Unity3D
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/18: Рейтинг темы: голосов - 18, средняя оценка - 4.50
1149 / 312 / 161
Регистрация: 30.07.2022
Сообщений: 1,791
Записей в блоге: 4

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

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

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

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

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

Буду рад любым советам.
Заранее спасибо!
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.09.2022, 23:24
Ответы с готовыми решениями:

Перемещение персонажа
При перемещении персонажа вправо, перемещение происходит плавное. При перемещении персонажа влево, персонаж начинает дёргаться, как...

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

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

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

возможно мне подойдет паттерн состояния для переключения скорости.
Я нашел видео и понял как они создаются.
Но в конце автор показал дулю! Управляя переключениями между состояниями простыми if =(
0
52 / 35 / 16
Регистрация: 03.08.2019
Сообщений: 389
12.09.2022, 12:45
devillived, не понимаю зачем так заморачиваться... делайте так чтобы сами понимали, что написали. чем проще код тем лучше - имхо)
0
1149 / 312 / 161
Регистрация: 30.07.2022
Сообщений: 1,791
Записей в блоге: 4
12.09.2022, 12:55  [ТС]
Fantom1987, проблема в том, что проще не работает.
и если я захочу добавить бег на корточках например. мне прийдется ТАКОЕ городить!!!
вот я и ищу способ простой реализации ветвления условий с возможностью расширения.
0
52 / 35 / 16
Регистрация: 03.08.2019
Сообщений: 389
12.09.2022, 13:13
писал под 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
1149 / 312 / 161
Регистрация: 30.07.2022
Сообщений: 1,791
Записей в блоге: 4
12.09.2022, 13:35  [ТС]
Fantom1987, Спасибо!
Я знаком с данной конструкцией.
Это по сути те же ифы, то лько завернутые в switch case.

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

Всем спасибо! Всем удачи.
0
 Аватар для samana
2639 / 1567 / 853
Регистрация: 23.02.2019
Сообщений: 3,876
12.09.2022, 21:56
Лучший ответ Сообщение было отмечено 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
1149 / 312 / 161
Регистрация: 30.07.2022
Сообщений: 1,791
Записей в блоге: 4
12.09.2022, 22:18  [ТС]
samana, Восхитительно!
Спасибо большое!


Удивительно! я понимаю, что там написано. Вы все классно написали!
0
 Аватар для samana
2639 / 1567 / 853
Регистрация: 23.02.2019
Сообщений: 3,876
12.09.2022, 22:36
Цитата Сообщение от devillived Посмотреть сообщение
Удивительно! я понимаю, что там написано.
devillived, Благодарю. Честно говоря удивлён, что код оказался понятным со стороны.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.09.2022, 22:36
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru