C# 四元数lookRotation-向上不';行不通
我试着让一只鸟旋转得有点“真实”,也就是说,矢量向上应该指向旋转的角度,我的意思是,如果你向右旋转90º,矢量向上现在应该指向-vector.forward(旋转前的那个) 我尝试了一个函数,但它只是偶尔旋转,其余的,它只是覆盖了向量。向上,好像它是0,1,0C# 四元数lookRotation-向上不';行不通,c#,unity3d,quaternions,C#,Unity3d,Quaternions,我试着让一只鸟旋转得有点“真实”,也就是说,矢量向上应该指向旋转的角度,我的意思是,如果你向右旋转90º,矢量向上现在应该指向-vector.forward(旋转前的那个) 我尝试了一个函数,但它只是偶尔旋转,其余的,它只是覆盖了向量。向上,好像它是0,1,0 using System.Collections; using System.Collections.Generic; using UnityEngine; public class SmoothPath : MonoBehavi
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmoothPath : MonoBehaviour {
[System.Serializable]
public class TrackingSettings
{
[HideInInspector]
public int currentPoint = 0;
[HideInInspector]
public int nextPoint = 1;
public int pathToFollow = 0;
public GameObject affectedObject;
public float speed = 10;
public float rotationSpeed = 12;
[HideInInspector]
public Quaternion lastRotation;
[HideInInspector]
public Vector3 lastLocation;
}
[System.Serializable]
public class PathsToFollow
{
public GameObject pathReference;
public Transform[] pathPoints;
}
public TrackingSettings[] objectsToTrack;
private TrackingSettings tempObjectToTrack;
private float timer = 0;
public PathsToFollow[] pathsToFollow;
private Quaternion lookRotation;
private Transform currentNode;
private Transform nextNode;
private float distance;
// Use this for initialization
void Start()
{
foreach (TrackingSettings ts in objectsToTrack)
{
ts.currentPoint = 0;
ts.nextPoint = 1;
ts.affectedObject.transform.position = pathsToFollow[ts.pathToFollow].pathPoints[0].position;
ts.lastRotation = ts.affectedObject.transform.rotation;
ts.lastLocation = ts.affectedObject.transform.position;
lookRotation = Quaternion.LookRotation(pathsToFollow[ts.pathToFollow].pathPoints[1].position - pathsToFollow[ts.pathToFollow].pathPoints[0].position);
ts.affectedObject.transform.rotation = lookRotation;
currentNode = pathsToFollow[ts.pathToFollow].pathPoints[ts.currentPoint];
nextNode = pathsToFollow[ts.pathToFollow].pathPoints[ts.nextPoint];
distance = Vector3.Distance(currentNode.position, nextNode.position);
}
}
// Update is called once per frame
void Update () {
timer += Time.deltaTime;
for (int i = 0; i < objectsToTrack.Length; i++)
{
tempObjectToTrack = objectsToTrack[i];
if (Vector3.Distance(tempObjectToTrack.affectedObject.transform.position, nextNode.position) < 0.3f)
{
tempObjectToTrack.currentPoint = tempObjectToTrack.nextPoint;
tempObjectToTrack.nextPoint++;
//reset if overflow
if (tempObjectToTrack.nextPoint == pathsToFollow[tempObjectToTrack.pathToFollow].pathPoints.Length) tempObjectToTrack.nextPoint = 0;
timer = 0;
//lastNode = pathsToFollow[tempObjectToTrack.pathToFollow].pathPoints[tempObjectToTrack.lastPoint];
currentNode = pathsToFollow[tempObjectToTrack.pathToFollow].pathPoints[tempObjectToTrack.currentPoint];
nextNode = pathsToFollow[tempObjectToTrack.pathToFollow].pathPoints[tempObjectToTrack.nextPoint];
distance = Vector3.Distance(currentNode.position, nextNode.position);
float angle = GetAngle(tempObjectToTrack.affectedObject.transform.forward, Vector3.Normalize(nextNode.position - currentNode.position));
//set last rotation and location
tempObjectToTrack.lastRotation = tempObjectToTrack.affectedObject.transform.localRotation;
tempObjectToTrack.lastLocation = tempObjectToTrack.affectedObject.transform.position;
tempObjectToTrack.affectedObject.transform.up = new Vector3(angle / 2, 45, 0);
lookRotation = Quaternion.LookRotation(nextNode.position - tempObjectToTrack.affectedObject.transform.position, new Vector3(angle / 2, 45, 0));
Debug.Log("Up: " + new Vector3(angle / 2, 45, 0) + " - angle: " + angle);
//tempObjectToTrack.affectedObject.transform.localRotation = lookRotation;
}
tempObjectToTrack.affectedObject.transform.position = Vector3.SlerpUnclamped(tempObjectToTrack.lastLocation, nextNode.position, timer / distance * tempObjectToTrack.speed);
tempObjectToTrack.affectedObject.transform.rotation = Quaternion.Slerp (tempObjectToTrack.lastRotation, lookRotation, timer / distance * tempObjectToTrack.rotationSpeed);
}
}
private float GetAngle(Vector3 a, Vector3 b)
{
b.y = 0;
a.y = 0;
float angle = Vector3.Angle(a, b);
float sign = Mathf.Sign(Vector3.Dot(Vector3.up, Vector3.Cross(a, b)));
return angle * sign;
}
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
公共类平滑路径:单行为{
[系统可序列化]
公共类跟踪设置
{
[hideininstecpt]
公共int currentPoint=0;
[hideininstecpt]
公共int nextPoint=1;
public int pathToFollow=0;
公共游戏对象影响对象;
公共浮动速度=10;
公共浮球旋转速度=12;
[hideininstecpt]
公共四元数;
[hideininstecpt]
公共矢量3最新位置;
}
[系统可序列化]
公共类路径跟踪
{
公共游戏对象路径引用;
公共交通点;
}
公共跟踪设置[]对象跟踪;
私人跟踪设置tempObjectToTrack;
专用浮点计时器=0;
公共路径跟踪[]路径跟踪;
私有四元数旋转;
私有变换节点;
私有转换nextNode;
私人浮动距离;
//用于初始化
void Start()
{
foreach(对象跟踪中的跟踪设置ts)
{
ts.currentPoint=0;
ts.nextPoint=1;
ts.affectedObject.transform.position=pathsToFollow[ts.pathToFollow]。路径点[0]。位置;
ts.lastRotation=ts.affectedObject.transform.rotation;
ts.lastLocation=ts.affectedObject.transform.position;
lookRotation=Quaternion.lookRotation(路径跟踪[ts.pathToFollow]。路径点[1]。位置-路径跟踪[ts.pathToFollow]。路径点[0]。位置);
ts.affectedObject.transform.rotation=lookRotation;
currentNode=pathsToFollow[ts.pathToFollow].pathPoints[ts.currentPoint];
nextNode=pathsToFollow[ts.pathtfollow].pathPoints[ts.nextPoint];
距离=矢量3.距离(currentNode.position,nextNode.position);
}
}
//每帧调用一次更新
无效更新(){
timer+=Time.deltaTime;
for(int i=0;i
在圆形路径中(四个或更多的路径点以正方形/圆形排列),鸟有时会正确地指向,而有些鸟则不会我不会为此使用
LookRotation
,因为你不知道你想要本地向上
的方向。下面是一种直接使用角度来更改滚动的替代方法:
首先,我们将GetAngle
的结果钳制为+/-90f
float angle = GetAngle(tempObjectToTrack.affectedObject.transform.forward, Vector3.Normalize(nextNode.position - currentNode.position));
angle = Mathf.Clamp(angle,-90f,90f);
然后,我们面对面向下一个目标的对象,局部向上
为全局向上
,然后通过将其乘以滚动旋转来滚动该数量:
lookRotation = Quaternion.LookRotation(nextNode.position - tempObjectToTrack.affectedObject.transform.position, Vector3.up);
// If the direction of roll isn't right, try `-1 * angle` here:
lookRotation = lookRotation * Quaternion.AngleAxis(angle, Vector3.forward);
然后,将Slerp
edlookRotation
分配给rotation
:
tempObjectToTrack.affectedObject.transform.rotation = Quaternion.Slerp (tempObjectToTrack.lastRotation, lookRotation, timer / distance * tempObjectToTrack.rotationSpeed);