簡體   English   中英

如何將 object 緩慢旋轉到目標平滑? object 沒有面向目標旋轉

[英]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

在位置 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM