簡體   English   中英

為什么在將 object 移向目標時,如果目標距離很遠,object 移動得非常快,但如果目標很近,它移動得更慢?

[英]Why when moving an object towards a target if the target is far away the object move very fast but if the target is close it's moving slower?

我希望它像近距離物體一樣移動得更慢。

小立方體從玩家手中移動到右邊的大立方體。 右邊的大立方體是目標。

目標移動較慢平穩

這是播放器根目錄 object,附有腳本,投擲速度設置為 0.5f

腳本附上

這是更新中的腳本,我正在調用 ThrowObject 方法:

using UnityEngine;
using System;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;

[RequireComponent(typeof(Animator))]
public class IKControl : MonoBehaviour
{
    public InteractableItem[] lookObj = null;
    public GameObject objToThrow;
    public Text text;
    public Text textMultiLine;
    public float weightDamping = 1.5f;
    public float maxDistance = 10f;
    public bool RightHandToTarget = true;
    public float throwSpeed;

    private List<InteractableItem> allDetectedItems;
    private Animator animator;
    private InteractableItem lastPrimaryTarget;
    private Quaternion savedRotation;
    private float lerpEndDistance = 0.1f;
    private float finalLookWeight = 0;
    private bool transitionToNextTarget = false;
    private InteractableItem target;
    private bool throwObj = false;

    void Start()
    {
        animator = GetComponent<Animator>();
        allDetectedItems = new List<InteractableItem>();
    }

    // Callback for calculating IK
    void OnAnimatorIK()
    {
        if (lookObj != null)
        {
            InteractableItem primaryTarget = null;
            float closestLookWeight = 0;

            // Here we find the target which is closest (by angle) to the players view line
            allDetectedItems.Clear();
            foreach (InteractableItem target in lookObj)
            {
                Vector3 lookAt = target.transform.position - transform.position;
                lookAt.y = 0f;

                // Filter out all objects that are too far away
                //if (lookAt.magnitude > maxDistance) continue;
                if (lookAt.magnitude > target.distance) continue;

                float dotProduct = Vector3.Dot(new Vector3(transform.forward.x, 0f, transform.forward.z).normalized, lookAt.normalized);
                float lookWeight = Mathf.Clamp(dotProduct, 0f, 1f);
                if (lookWeight > 0.1f && lookWeight > closestLookWeight)
                {
                    closestLookWeight = lookWeight;
                    primaryTarget = target;
                    allDetectedItems.Add(target);
                }
            }

            if (primaryTarget != null)
            {
                if ((lastPrimaryTarget != null) && (lastPrimaryTarget != primaryTarget) && (finalLookWeight > 0f))
                {
                    // Here we start a new transition because the player looks already to a target but
                    // we have found another target the player should look at
                    transitionToNextTarget = true;
                }
            }

            // The player is in a neutral look position but has found a new target
            if ((primaryTarget != null) && !transitionToNextTarget)
            {
                lastPrimaryTarget = primaryTarget;
                //finalLookWeight = Mathf.Lerp(finalLookWeight, closestLookWeight, Time.deltaTime * weightDamping);
                finalLookWeight = Mathf.Lerp(finalLookWeight, 1f, Time.deltaTime * weightDamping);
                float bodyWeight = finalLookWeight * .75f;
                animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
                animator.SetLookAtPosition(primaryTarget.transform.position);

                if (RightHandToTarget)
                {
                    Vector3 relativePos = primaryTarget.transform.position - transform.position;
                    Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
                    animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 1f * closestLookWeight);
                    animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);

                    // -> new code block
                    if (finalLookWeight > 0.95f) // here you can play with a value between 0.95f -> 1.0f
                    {
                        // call your funtion to shoot something here
                        throwObj = true;
                        target = primaryTarget;
                    }
                }
            }

            // Let the player smoothly look away from the last target to the neutral look position
            if ((primaryTarget == null && lastPrimaryTarget != null) || transitionToNextTarget)
            {
                finalLookWeight = Mathf.Lerp(finalLookWeight, 0f, Time.deltaTime * weightDamping);
                float bodyWeight = finalLookWeight * .75f;
                animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
                animator.SetLookAtPosition(lastPrimaryTarget.transform.position);

                if (RightHandToTarget)
                {
                    Vector3 relativePos = lastPrimaryTarget.transform.position - transform.position;
                    Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
                    animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.5f * closestLookWeight);
                    animator.SetIKPosition(AvatarIKGoal.RightHand, lastPrimaryTarget.transform.position);
                }

                if (finalLookWeight < lerpEndDistance)
                {
                    transitionToNextTarget = false;
                    finalLookWeight = 0f;
                    lastPrimaryTarget = null;
                }
            }

            // Show primary object found by the player
            if (primaryTarget != null) text.text = "Item found: " + primaryTarget.description;
            else text.text = "Item found: none";

            // Show all objects found by the player
            if (allDetectedItems.Count > 0)
            {
                string result = "";
                foreach (InteractableItem item in allDetectedItems)
                {
                    result += item.description + "\n";
                }
                textMultiLine.text = result;
            }
            else
            {
                textMultiLine.text = "No items found.";
            }
        }
    }

    private void ThrowObject()
    {
        objToThrow.transform.position = Vector3.Lerp(objToThrow.transform.position, target.transform.position, throwSpeed * Time.deltaTime);
    }

    private void Update()
    {
        if (throwObj == true)
        {
            ThrowObject();
        }
    }
}

問題是當玩家面對巨大的遠方太空船時,立方體正在向太空船移動,它移動得非常快,我幾乎看不到立方體在移動。 不確定為什么它移動到近距離目標時緩慢而平滑,但移動到遠距離目標時卻非常快?

對於移動,您使用 function Vector3.Lerp(Vector3 a, Vector3 b, float t) 它使用以下公式找到ab之間的交集值formula: a + (b - a) * t

讓我們假設 z 位置無關緊要,並且 main object position [0,0]讓我們看看以下情況:

  • 目標 object 在主目標旁邊 它的 position 是[10, 10] 我們的主要 object 通過變量float t從起點 position 移動到目標 position。 讓我們計算主對象的 position 如果t是,例如: 0.10.20.3 (顯然如果它是0主對象的 position 是開始 position,如果它是1主對象的 8811773473171817 FOR3MU:3817 FOR3MU : 3817 (b - a) * t
    1) [0,0] + ([10,10] - [0,0]) * 0.1 = [0,0] + [10,10]*0.1 = [0,0] + [1,1] = [1,1]
    2) [0,0] + ([10,10] - [0,0]) * 0.2 = [0,0] + [10,10]*0.2 = [0,0] + [2,2] = [2,2]
    3) [0,0] + ([10,10] - [0,0]) * 0.3 = [0,0] + [10,10]*0.3 = [0,0] + [3,3] = [3,3]

我們得到,將變量t改變0.1會導致 position 改變[1,1]個單位。

  • 目標 object 是第一次的50倍。 它的 position 現在是[500,500] 我們讓t原樣: 0.1 and 0.2 and 0.3 計數:公式:a + (b - a) * t
    1) [0,0] + ([500,500] - [0,0]) * 0.1 = [0,0] + [500,500]*0.1 = [0,0] + [50,50] = [50,50]
    2) [0,0] + ([500,500] - [0,0]) * 0.2 = [0,0] + [500,500]*0.2 = [0,0] + [100,100] = [100,100]
    3) [0,0] + ([500,500] - [0,0]) * 0.3 = [0,0] + [500,500]*0.3 = [0,0] + [150,150] = [150,150]

這里將變量t改變0.1會導致 position 改變[50,50]個單位。

因此,對象之間的距離越大,主對象的 position 變化越快。

嗯,這是對你做錯了什么的解釋。 現在決定:

您應該使用 function transform.Translate(Vector3 translation)
這個 function 在參數 Vector3 translate 的方向移動 object。 當然,如果平移等於 [1,0,0],則 object 移動到正 x,如果 [-1,0,0] - 移動到負 x,如果 [0,1,0] - 移動到正 y,如果 [0 ,-1,0] - 負 y 等等。

如何獲得此 Vector3 translation 您必須從目標 position 中減去對象的 position。然后您應該對其進行歸一化(以便值不大於 1 且不小於 0)。 代碼看起來是這樣的:

Vector3 dir; // direction of moving. This parameter will be given to the function Translate()
GameObject targetPosition; // Target position
float speed; // The speed of moving. Recommended to be set from inspector
private void ThrowObject () {
    dir = targetPosition - transform.position;
    transform.Traslate(dir.normalized*Time.deltaTime*speed);
}
private void Update () {
    ThrowObject();
}

PS 我們將dir乘以Time.deltaTime使移動速度在快速和慢速計算機(平板電腦、手機...)上相同

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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