Третий час бьюсь над косяком в скрипте, кто поможет?
В общем задача скрипта практически завершена, но периодически появляются глюки.
Скрипт по команде кнопок WSAD (это пока-что) перекатывает юнит на соседнее поле. RotationPivot - объект который используется как точка через которую идет перекатывание.
Скрипт работает как часы, но в некоторых позициях (например при последовательности W-A-W) юнит начинает перекатываться через другую ось (а именно ось Y, хотя скрипт однозначно вращает только по X и Z) - как можно вылечить?
using UnityEngine;
using System.Collections;
public class Unit : MonoBehaviour {
private string UnitName; // Наименование юнита
public int unitNSPosition, unitWEPosition; //Позиция юнита в координатах
public Transform RotationPivot; // Точка вращения юнита
public Quaternion RotateFrom, RotateTo; // Кватернионы вращения (начало-конец)
}
public class MoveGamer : Unit {
public bool UnitSetMove; // Переменная отвечающая за инициализацию вектора
public bool UnitIsMove; // Движется ли юнит?
public float UnitCurrentAngle; // Скорость вращения юнита
public float CurrentUnitAngleNS, CurrentUnitAngleAround, CurrentUnitAngleWE; // Текущий уровень поворота юнита
public string UnitDirection; // Направление движения
public enum Sector {SectorI, SectorII, SectorIII, SectorIV} // Ориентация секторов для определени углов поворота
public Sector CurrentSectorNS, CurrentSectorWE, CurrentSectorAround; // Сектор текущего поворота по осям Север-Юг, Запад-Восток, Вокруг себя
void Start () {
UnitCurrentAngle = 0;
UnitIsMove = false;
UnitSetMove = false;
CurrentSectorNS = CurrentSectorWE = CurrentSectorAround = Sector.SectorI;
}
void Update () {
UnitWaitMove (); // Юнит ожидает движение
}
public void UnitWaitMove () {
// Блок выбора направления движения (времянка)
if ((Input.GetKeyDown(KeyCode.W)) & !(UnitSetMove)) UnitDirection = "North"; // север
if ((Input.GetKeyDown(KeyCode.S)) & !(UnitSetMove)) UnitDirection = "South"; // юг
if ((Input.GetKeyDown(KeyCode.D)) & !(UnitSetMove)) UnitDirection = "East"; // восток
if ((Input.GetKeyDown(KeyCode.A)) & !(UnitSetMove)) UnitDirection = "West"; // запад
if ((UnitDirection != "") & !UnitIsMove) SetPointToRotation (); // Если команда задана, то инициировать точку поворота
if (UnitIsMove) RotatePlayerUnit (); // Если юнит в движении то выполнить поворот
}
public void RotatePlayerUnit() {
RotationPivot.transform.rotation = Quaternion.Lerp(RotateFrom,RotateTo, UnitCurrentAngle); // Повернуть юнит
UnitCurrentAngle += 0.1f; // изменение угла
if (UnitCurrentAngle > 1f) StopMove (); // Если поворот завершен, то остановить движение
}
// метод меняющий значение сектора поворота
public Sector ChangeSector(Sector ChangeSector, int Direct) {
int Sec = (int)ChangeSector; // переменная показывающая текущий сектор
Sec += Direct; // увеличение/уменьшение сектора в зависимости от входного параметра
Sec = (Sec > (int)Sector.SectorIV) ? 0 : Sec;
Sec = (Sec < (int)Sector.SectorI) ? 3 : Sec; //условия перехода сектора через 0
ChangeSector = (Sector)Sec; // установка сектора
return ChangeSector; // возврат метода
}
public void SetPointToRotation () {
// задаем смещение позиции родительского элемента относительно юнита, для вращения
float SetX, SetZ; //переменные позиции родителя
SetX = SetZ = 0f;
RotateFrom = transform.rotation; // Снять "слепок" текущего значения поворота
switch (UnitDirection) { // установка точки поворота
case "North":
SetX = 0.5f; SetZ = 0f; // позиция точки относительно юнита
CurrentUnitAngleWE -= 90f; // приращение угла
CurrentUnitAngleWE = (CurrentUnitAngleWE < 0) ? 270 : CurrentUnitAngleWE; // проход угла через 0
break;
case "South":
SetX = -0.5f; SetZ = 0f;
CurrentUnitAngleWE += 90f;
CurrentUnitAngleWE = (CurrentUnitAngleWE > 360) ? 90 : CurrentUnitAngleWE;
break;
case "West":
SetX = 0f; SetZ = 0.5f;
CurrentUnitAngleNS += 90f;
CurrentUnitAngleNS = (CurrentUnitAngleNS > 360) ? 90 : CurrentUnitAngleNS;
break;
case "East":
SetX = 0f; SetZ = -0.5f;
CurrentUnitAngleNS -= 90f;
CurrentUnitAngleNS = (CurrentUnitAngleNS < 0) ? 270 : CurrentUnitAngleNS;
break;
}
RotateTo = Quaternion.Euler(CurrentUnitAngleNS, CurrentUnitAngleAround, CurrentUnitAngleWE); // установка кватерниона поворота
RotationPivot.position = new Vector3(transform.position.x + SetX, transform.position.y - 0.5f, transform.position.z + SetZ); // устанавливаем точку вращения
this.transform.parent = RotationPivot.transform; // привязываем юнит к родителю
UnitIsMove = true; // начнаем вращение
UnitSetMove = false; // заканчиваем инициализацию
}
public void StopMove () {
switch (UnitDirection) {
case "North":
CurrentSectorNS = ChangeSector (CurrentSectorNS, -1); // изменение сектора вращения
unitNSPosition += 1; // изменить позицию
break;
case "South":
CurrentSectorNS = ChangeSector (CurrentSectorNS, 1);
unitNSPosition -= 1;
break;
case "West":
CurrentSectorWE = ChangeSector (CurrentSectorWE, 1);
unitWEPosition += 1;
break;
case "East":
CurrentSectorWE = ChangeSector (CurrentSectorWE, -1);
unitWEPosition -= 1 ;
break;
}
// блок завершения движения
RotationPivot.rotation = RotateTo; // выровнять угол поворота (доводчик)
UnitCurrentAngle = 0f; // обнулить угол
transform.parent = null; // овязать точку вращения
UnitIsMove = false; // закончить движение
UnitDirection = ""; // обнулить команду на движение
}
}