[英]How can i make object to rotate smooth towards a target with raycast?
[英]How to rotate object towards target smooth slowly ? The object is not rotating facing the target
最后的目標是在他開始移動時旋轉 object,這樣 object 將面向他正在移動的目標,並且從 object 眼睛發出的激光將面向相同的目標。
我要旋轉的 object 首先是 position 0,0,0 因為 object 是一個孩子。 玩家手持object。 然后 object 和 animation 一起被扔向一個目標。
object 正在向目標移動,但現在我希望 object 也能平滑地緩慢旋轉到目標,在這種情況下,我將旋轉持續時間設置為 1 秒。 我看到 object 旋轉正在改變但沒有面向目標。
此屏幕截圖顯示 object 仍在玩家手中,位置為 position 0,0,0
然后 object get throw 並開始向目標移動,此時 object 旋轉變化:
投擲有孩子的 object 會改變眼睛,應該從眼睛射出激光束,然后我想讓 object 朝目標旋轉,這樣眼睛發出的激光就會朝向目標。
我用一個小紅圈標記了眼睛:
在這張截圖中,我把目標標記在很遠的地方,綠色的激光沒有朝向目標,眼睛也沒有朝向目標。 激光應該從眼睛出來,整個 object 應該面對目標,所以激光也應該用眼睛面對目標。
此屏幕截圖是 object 在運行游戲之前眼睛朝前與 object 的屏幕截圖。這只是為了表明眼睛與朝前的 object 對齊。
這個腳本附在我的播放器上,讓 object 被扔向目標,也應該讓 object 向目標旋轉:
使 object 移動到目標的投擲部分工作正常但旋轉部分不是:
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transformRot = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t += Time.deltaTime;
}
transformRot = targetRot;
}
我還看到制作 transformRot = targetRot; 出於某種原因,有一條小消息說不必要的分配不知道為什么。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThrowObject : MonoBehaviour
{
public Transform objectToThrow;
public Transform target;
public Transform objectToThrowParent;
public float throwingSpeed;
public float waitAtTargetTime;
public float distanceToStopFromTarget;
public bool go = false;
public AnimationCurve animationCurve;
private Animator anim;
private bool startThrowAnimationOnce = true;
private bool reParent = false;
private bool startMovingBack = false;
private void Start()
{
anim = GetComponent<Animator>();
}
private void Update()
{
if (anim != null && startThrowAnimationOnce)
{
anim.SetTrigger("Throw");
startThrowAnimationOnce = false;
}
if (go)
{
objectToThrow.parent = null;
StartCoroutine(Throw());
StartCoroutine(AnimateRotationTowards(objectToThrow.rotation, target.rotation, 1f));
go = false;
}
if (reParent)
{
objectToThrow.position = objectToThrowParent.position;
}
if (startMovingBack)
{
if (Vector3.Distance(objectToThrow.position, objectToThrowParent.position) >= 0.1f)
{
float step = 5 * Time.deltaTime;
objectToThrow.position = Vector3.MoveTowards(objectToThrow.position, objectToThrowParent.position, step);
}
else
{
objectToThrow.position = objectToThrowParent.position;
objectToThrow.parent = objectToThrowParent;
objectToThrow.localPosition = new Vector3(0, 0, 0);
}
}
}
public void ThrowEvent()
{
go = true;
}
IEnumerator Throw()
{
while(Vector3.Distance(objectToThrow.position, target.position) >= distanceToStopFromTarget)
{
objectToThrow.position = Vector3.MoveTowards(
objectToThrow.position,
target.position,
throwingSpeed * Time.deltaTime
);
yield return null;
}
yield return new WaitForSeconds(waitAtTargetTime);
startMovingBack = true;
}
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transformRot = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t += Time.deltaTime;
}
transformRot = targetRot;
}
}
此腳本附加到 object 眼睛並發射激光:此腳本中的目標與 ThrowObject 腳本中的目標相同:
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class Hovl_DemoLasers : MonoBehaviour
{
public List<Transform> targets;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
private float buttonSaver = 0f;
private Hovl_LaserDemo hovl_laserDemo;
private float maxDistance = 0;
private int closestIndex = 0;
void Start()
{
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter(+1);
}
buttonSaver += Time.deltaTime;
if (startLaser)
{
rotateMouse = false;
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
hovl_laserDemo = Instance.GetComponent<Hovl_LaserDemo>();
startLaser = false;
}
if (targets != null)
{
maxDistance = Mathf.Infinity;
for (int i = 0; i < targets.Count; i++)
{
float distance = Vector3.Distance(gameObject.transform.position, targets[i].position);
if (distance < maxDistance)
{
maxDistance = distance;
closestIndex = i;
}
}
if (hovl_laserDemo != null)
{
float distance = Vector3.Distance(gameObject.transform.position, targets[closestIndex].position);
MaxLength = distance;
hovl_laserDemo.MaxLength = distance;
}
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, targets[closestIndex].position);
}
else
{
RotateToMouseDirection(gameObject, targets[closestIndex].position);
}
}
if (Cam != null && rotateMouse)
{
RaycastHit hit;
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
void Counter(int count)
{
Prefab += count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
void RotateToMouseDirection(GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
在這種情況下,了解按值傳遞或按引用傳遞之間的區別很重要。 在您的AnimateRotationTowards
function 中,該 function 的所有參數均按值傳遞。 對這些旋轉的更改將影響 function scope 中的局部值,但這些值與場景中使用的值不同。
您可能想要的是對某些Transform
object 的引用。如果您為該變換分配新的旋轉,它將在場景中使用該旋轉。
看起來這個腳本組件附加到將要旋轉的游戲對象。 是對的嗎? 如果是,您可以通過為transform.rotation
賦值來設置新的旋轉:
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transform.rotation = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t += Time.deltaTime;
}
transform.rotation = targetRot;
}
如果您需要將旋轉分配給其他某個游戲對象,您可以傳入對該游戲對象或其變換的引用,並使用它來分配旋轉。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.