gpt4 book ai didi

unity3d - 通过输入方向查找游戏对象

转载 作者:行者123 更新时间:2023-12-02 01:05:37 26 4
gpt4 key购买 nike

Example

我将游戏对象列表添加到区域内的列表中,如图所示。我需要的是从原点选择目标的定向输入。我已经得到了这个原点。

我的第一次尝试是通过 rayCast 获取它,但有时定向输入需要通过射线直接击中目标对象。如果输入像案例 #1 那样完成,这没有问题。

但是,我需要它真正起作用的是,当输入方向与情况 #2 或 #3 一样时,输入仍会获得目标。我的第二次尝试是使用 sphereCast 来做到这一点,但它仍然需要一个接近球体的目标,并且 sphereCast 击中的多个目标仍然需要通过输入产生一个更准确的目标选择。

因为我拥有所有可能目标的所有 transform.position 以及原点,所以我想知道是否有一种更优雅的方法可以通过比较这些坐标的 vector3(一般方向上的原点和目标)来解决这个问题。

这是我的最新方法:

//
// m_targetList is the list containing all GameObjects as GameObjects in other script m_collector. All m_collector does is this.
//

using System.Collections.Generic;
using UnityEngine;

public class TargetSwitcher : MonoBehaviour
{
private TargetCollector m_collector;
private Transform m_origin;

public bool m_targetChanged = false;

public GameObject m_target;

public LayerMask m_targetMask;

private Dictionary<Vector3, float> m_targetInfo = new Dictionary<Vector3, float>();

private void Awake()
{
m_collector = GetComponent<TargetCollector>();
m_origin = GameObject.Find("TargetOrigin").transform;
m_tracker = GameObject.Find("TargetTracker").transform;
m_bound = GetComponent<BoxCollider>();
}

public void UpdateBearing(GameObject origin)
{
m_origin = origin.transform;

foreach (GameObject target in m_collector.m_targetList)
{
Vector3 dir = (target.transform.position - origin.transform.position).normalized
float dist = Vector3.Distance(origin.transform.position, target.transform.position);

m_targetInfo.Add(dir, dist);
}
}

public void SwitchTarget()
{
if (!m_targetChanged)
{
Vector2 dir = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")).normalized;

// Find closest direction value from Dictionary to dir of here
// Compare distance from origin if multiple targets and choose the nearest
}
}

public void ReturnToIdle()
{
m_origin.position = m_target.transform.position;
m_targetChanged = false;
m_targetInfo.Clear();
}

public struct TargetInfo
{
public Vector3 bearing;
public float distance;

public TargetInfo(Vector3 bearing, float distance)
{
this.bearing = bearing;
this.distance = distance;
}
}
}

一般来说,我试图在 SwitchTarget() 之前将定向输入的归一化向量与从原点到每个目标的归一化向量进行比较。这里的输入法是Gamepad axis x and y as Horizo​​ntal and Vertical。

重新发布此问题,因为提供的答案与问题相距甚远并标记为重复(给定的答案是关于仅按距离查找游戏对象,此问题是关于方向和距离部分是在找到多个项目时进行二手比较方向)

编辑

现在对点积进行了一些试验后,我确信这很可能是我想去的地方。不过,我需要继续处理很多不一致的地方。这是我最近的尝试:

private void Update()
{
UpdateBearing();

Vector3 input = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);

if (input != Vector3.zero)
{
SwitchTarget();
}
}

public void UpdateBearing(GameObject origin)
{
m_origin.position = origin.transform.position;

foreach (GameObject target in m_collector.m_targetList)
{
Vector3 dir = (target.transform.position - origin.transform.position).normalized;
if (!m_targetInfo.ContainsKey(target))
{
m_targetInfo.Add(target, dir);
}
}
}

public void SwitchTarget()
{
GameObject oldTarget = m_collector.m_target;

if (!m_targetChanged)
{
Vector3 dir = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0).normalized;
Debug.DrawRay(m_origin.position, dir * 100, Color.yellow, 0.5f);

foreach (KeyValuePair<GameObject, Vector3> possibleTarget in m_targetInfo)
{
float dot = Vector3.Dot(dir, possibleTarget.Value);

if (dot > 0.5f) // Compare DP difference of added dot and input dot
{
GameObject newTarget = possibleTarget.Key;

if (oldTarget != newTarget)
{
Debug.Log(possibleTarget.Value + " // " + dot);

m_target = newTarget;
m_collector.m_target = newTarget;
m_targetChanged = true;
}
}
}
}
}

有了这个,我就可以在没有光线转换和丢失任何目标的情况下获得游戏对象选择。但是,我确定我需要比 if(dot > 0.5f) 更好的大小写比较。另外,我的粗略假设是,如果我不为每个 Key 更新字典 m_targetInfo 的值,那么如果这些目标移动,我就会有另一个不一致。无论如何,我仍然对如何正确利用它来实现我的最终目标感到困惑。

最佳答案

因为您在该区域拥有所有需要的游戏对象,您可以创建一个 for 循环并检查您的视线方向和它们的位置之间的角度,如果它低于某个值(您可以将它设置得非常低以便它是精确的或稍微高一点以允许一些误差)将其放入游戏对象列表中,如果有多个对象,则获取最接近的对象。

获取角度最近的对象的代码如下所示:

GameObject CheckObjects()
{
List<GameObject> InAngle = new List<GameObject>();

for(int i = 0; i < YourObjectsList.Count; i++)
{
GameObject tested = YourObjectsList[i];

Vector3 dir = tested.transform.position - origin.transform.forward;

// I'm assuming here that youre rotating your origin with the
directional input, not then instead of origin.transform.forward
place there your directional vector3

float angle = Vector3.Angle(dir, tested.transform.position);

if(angle <= desiredAngle)
{
InAngle.Add(tested);
}
}

GameObject closest = null;

for(int j = 0; j < InAngle.Count; i++)
{
GameObject tested = InAngle[i];

Vector3 dir1 = tested.transform.position - origin.transform.position;
Vector3 dir2 = closest.transform.position - origin.transform.position;

if(!closest)
{
closest = tested;
}
else
{
if(dir2.sqrMagnitude > dir1.sqrMagnitude)
{
closest = tested;
}
}
}

return closest;
}

关于unity3d - 通过输入方向查找游戏对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47647116/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com