简体   繁体   English

transform.LookAt() 问题

[英]transform.LookAt() issue

I am trying to make an AI that will follow the closest object, but the problem is that when the object gets close it will rotate vertically, which I think is because the transform.LookAt() rotates towards the center of the object.我正在尝试制作一个跟随最近的 object 的 AI,但问题是当 object 靠近时,它会垂直旋转,我认为这是因为 transform.LookAt() 向 ZA8CFDE6331BD59EB66AC96F8911 的中心旋转。 Is there a way to look at an object without rotating vertically?有没有办法在不垂直旋转的情况下查看 object? Here's the code for the AI这是AI的代码

using System.Collections.Generic;
using UnityEngine;

public class AI : MonoBehaviour
{
    [SerializeField] public float speed = 2f;

    public float SphereRadius;
    public LayerMask mask;

    private void FixedUpdate()
    {
        //Checks if theres any objects nearbye
        Collider[] hitColliders = Physics.OverlapSphere(transform.position, SphereRadius, mask, QueryTriggerInteraction.UseGlobal);
        //Gets all the transforms of the objects and stores them into an array
        List<Transform> Transforms = new List<Transform>();
        foreach (var hitCollider in hitColliders)
        {
            Transforms.Add(hitCollider.transform);
        }
        //Checks what's the closest object and rotates the AI towards that object
        transform.LookAt(
        GetClosestEnemy(
            Transforms.ToArray()
        ) 
        );
        transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }

    Transform GetClosestEnemy(Transform[] enemies)
    {
        Transform tMin = null;
        float minDist = Mathf.Infinity;
        Vector3 currentPos = transform.position;
        foreach (Transform t in enemies)
        {
            float dist = Vector3.Distance(t.position, currentPos);
            if (dist < minDist)
            {
                tMin = t;
                minDist = dist;
            }
        }
        return tMin;
    }
}

Instead of directly using the Transform overload use the one taking a Vector3 target position you can completely customize like eg而不是直接使用Transform重载,而是使用采用Vector3目标 position 您可以完全自定义,例如

var target = GetClosestEnemy(Transforms.ToArray());

var localDelta = transform.InverseTransformPoint(target.position);
// Now you can reset any of the axis you do not want to be taken into account e.g.
localDelta.z = 0;

transform.LookAt(transform.TransformPoint(localDelta));

Btw as a little tip magnitude (which is internally used by Vector3.Distance ) is significantly slower than the sqrMagnitude as the latter skips taking the square root.顺便说一句,作为一个小尖端magnitude (由Vector3.Distance内部使用)比sqrMagnitude慢得多,因为后者跳过了平方根。

For comparison both work the same so you can use为了比较两者的工作方式相同,因此您可以使用

Transform GetClosestEnemy(IEnumerable<Transform> enemies)
{
    Transform tMin = null;
    float minDist = Mathf.Infinity;
    Vector3 currentPos = transform.position;
    foreach (Transform t in enemies)
    {
        float dist = (t.position - currentPos).sqrMagnitude;
        if (dist < minDist)
        {
            tMin = t;
            minDist = dist;
        }
    }
    return tMin;
}

or if you re a fan of Linq you could also do或者如果你是 Linq 的粉丝,你也可以这样做

Transform GetClosestEnemy(IEnumerable<Transform> enemies)
{
    Vector3 currentPos = transform.position;
    return enemies.OrderBy(enemy => (enemy.position - currentPos).sqrMagnitude).FirstOrDefault();
}

Then you could also shrink down the rest and do然后你也可以缩小 rest 并做

Collider[] hitColliders = Physics.OverlapSphere(transform.position, SphereRadius, mask, QueryTriggerInteraction.UseGlobal);
var target = GetClosestEnemy(hitColliders.Select(collider => collider.transform));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM