Проблема с Unity
| |
SkorpyX | Дата: Вторник, 03 Ноября 2015, 23:18 | Сообщение # 1 |
участник
Сейчас нет на сайте
| Здравствуйте! Я написал ИИ для зомби, который вроде бы работает, но есть одна ошибка в коде, которую я не могу найти и исправить. Есть префаб зомби, у которого есть триггер, при входе в который, состояние зомби меняется на активное, а состояние mechanim меняется на "Run", если игрок появляется вне триггера, то всё работает нормально, но если игра начинается тогда, когда игрок уже находится в триггере, то анимации назначаются неправильно (вместо анимации бега проигрывается анимация сна, скорее всего я напутал с присвоением триггеров). Пожалуйста, помогите мне, я переписал код полностью несколько раз, но ошибка осталась. Прилагаю сам js код, скриншот mechanim и видео ошибки:
Код #pragma strict
enum ZombieState { Active, Inactive }; var state : ZombieState = ZombieState.Inactive;
@Header("Настройки зомби") var hp : float = 100; var zombieDeadPrefab : GameObject; @Space(8) var armLength : float = 1.5; var radius : float = 16; var detectionTreshold : float = 1; var maxInterest : float = 15;
// Локальные переменные private var target : Transform; private var interest : float;
private var agent : NavMeshAgent; private var animator : Animator; private var head : Transform;
private var canAttack : boolean = true;
function Start () { // Базовая настройка agent = GetComponent.<NavMeshAgent>(); animator = GetComponent.<Animator>(); head = transform.Find("Armature/Spin/Head"); animator.SetInteger("Run ID", Random.Range(0, 2)); animator.SetTrigger("Sleep"); }
function Update () { StateMachine(); if ((Input.GetKeyDown("e")) || (MobileInput.GetButtonDown("Jump"))) Die(); }
function StateMachine () { switch (state) { case ZombieState.Active : ActiveState(); break; case ZombieState.Inactive : InactiveState(); break; } }
function ActiveState () { if (Vector3.Distance(transform.position, target.position) > radius) { GoToSleep(); return; } switch (target.tag) { case "Player" : RunToTarget(); AttackTarget(); break; default : if (interest <= 0) { GoToSleep(); return; } interest -= Time.deltaTime; RunToTarget(); break; } }
function InactiveState () { }
function GoToSleep () { target = null; interest = 0; agent.ResetPath(); animator.SetTrigger("Sleep"); state = ZombieState.Inactive; }
function SetTarget (tg : Transform) { target = tg; if (state != ZombieState.Active) animator.SetTrigger("Run"); state = ZombieState.Active; }
function RunToTarget () { agent.SetDestination(target.position); animator.SetFloat("Blend", agent.velocity.magnitude / agent.speed); }
function AttackTarget () { if ((Vector3.Distance(transform.position, target.position) <= armLength) && (canAttack)) { animator.SetInteger("Attack ID", Random.Range(0, 3)); animator.SetTrigger("Attack"); canAttack = false; } }
function SetCanAttack () { canAttack = true; }
function Hit () { if (target == null) return; }
function Die () { var dead : ZombieDead = Instantiate(zombieDeadPrefab, transform.position, transform.rotation).GetComponent.<ZombieDead>(); dead.zombie = transform; dead.zombieMaterial = GetComponentInChildren.<SkinnedMeshRenderer>().sharedMaterial; dead.zombieVelocity = agent.velocity; dead.SetupMyself(); Destroy(gameObject); }
function OnTriggerEnter (other : Collider) { if ((state == ZombieState.Active) && (target.tag == "Player")) return; if (other.tag == "Player") { SetTarget(other.transform); return; } if (other.attachedRigidbody == null) return; if (other.attachedRigidbody.velocity.magnitude < detectionTreshold) return; if (target == null) { SetTarget(other.transform); interest = maxInterest; } if (other.attachedRigidbody.velocity.magnitude < target.GetComponent.<Rigidbody>().velocity.magnitude) return; SetTarget(other.transform); interest = maxInterest; }
Видео в процессе загрузки...
Добавлено (03 ноября 2015, 23:18) --------------------------------------------- Добавил видео (модель зомби не украдена с Unturned :D):
Сообщение отредактировал SkorpyX - Вторник, 03 Ноября 2015, 23:25 |
|
| |
KamiRonin | Дата: Вторник, 03 Ноября 2015, 23:37 | Сообщение # 2 |
почти ветеран
Сейчас нет на сайте
| Возможно событие OnTriggerEnter в проблемном случае происходит у тебя на таком этапе инициализации зомби, что получается такой результат.
попробуй задействовать OnTriggerStay с дополнительными условиями срабатывания в нем.. задействуй отладку - нужно выявить с какими состояниями и переменными попадает зомби в коллайдер..
Мыслю - значит программирую... Конструктивная критика - умных ведет к совершенству... Великие умы обсуждают идеи, средние - обсуждают поступки, а малые - людей.
Сообщение отредактировал KamiRonin - Среда, 04 Ноября 2015, 08:20 |
|
| |
SkorpyX | Дата: Среда, 04 Ноября 2015, 00:09 | Сообщение # 3 |
участник
Сейчас нет на сайте
| KamiRonin, спасибо за ответ! Мне начинает казаться, что это баг Unity. Я проводил тест с Debug.Log, в ходе которого выясил, что сначала идёт событие старта, а потом триггера, но когда задействуется аниматор, то происходит такая штука: Как правильно:
Код Start { animator.SetTrigger("Sleep"); }
OnTriggerEnter { animator.SetTrigger("Run"); }
Как происходит: Start { OnTriggerEnter { animator.SetTrigger("Run"); }
animator.SetTrigger("Sleep"); }
Получается, что событие триггера происходит как бы в середине события старта, такое вообще возможно?
Добавлено (04 ноября 2015, 00:03) --------------------------------------------- В старте ведь я присваивал Sleep, а во время входа в триггер выводит Idle. Возможно я понял в чём дело...
Добавлено (04 ноября 2015, 00:08) --------------------------------------------- Действительно! Если я правильно понял, то она возникает из за того, что OnTriggerEnter вызывается во время перехода между Idle и Sleep, который длится 0.1 секунду.
Добавлено (04 ноября 2015, 00:09) --------------------------------------------- Так и есть, решением оказалось присвоение Sleep статуса начального состояния (до этого был Idle).
|
|
| |
dzrone3488 | Дата: Суббота, 07 Ноября 2015, 03:53 | Сообщение # 4 |
участник
Сейчас нет на сайте
| Я бы вместо триггера использовал Vector3.Distance. Меньше запар
Я делаю игры, а вы в них играете! :) Моя группа по созданию игр - www.vk.com/dzrone
|
|
| |
SkorpyX | Дата: Суббота, 07 Ноября 2015, 17:52 | Сообщение # 5 |
участник
Сейчас нет на сайте
| dzrone3488, мой скрипт подразумевает, что целью может быть не только игрок, но и любой объект с Rigidbody и амплитудой скорости больше detectionTreshold, что и показано на видео
Сообщение отредактировал SkorpyX - Суббота, 07 Ноября 2015, 20:33 |
|
| |
|