【问题标题】:Unity - How to calculate new position for an object from pitch of another object in 3DUnity - 如何根据 3D 中另一个对象的间距计算一个对象的新位置
【发布时间】:2020-02-10 22:13:35
【问题描述】:

我想根据网格的间距计算一个新位置,以便使一个对象跟随我旋转的对象的顶部:

结果:

我无法将上面表示的方形对象作为线对象的子对象(在 Unity 对象层次结构中),因为旋转的对象可以随时看到其比例发生变化。

在这种情况下可以使用数学解决方案吗?

【问题讨论】:

  • 根据对象的实际情况,您可以将它们都作为一个通用游戏对象的父对象,该对象通过旋转来定义音高,然后可以使用自己的变换单独缩放“旋转对象”。这个问题有点太抽象了,无法确定这是否适合你。
  • @LukeBriggs 我无法修改 Unity 对象层次结构
  • 好的,是2D还是3D?
  • 是 3D 抱歉我已经更新了标题
  • 这些形状的通用性如何——它是立方体还是平面?或者可以是例如需要“粘”在任何形状物体表面的球体?

标签: unity3d


【解决方案1】:

热点

如果您想在通用对象上的特定位置放置可以在任何地方缩放或转换的东西,那么“热点”可能特别有用。

什么是热点?

编辑目标游戏对象(本例中的行)并向其添加一个空游戏对象。给它一个合适的名称——例如“交叉武器热点”,然后将其移动到您希望其他游戏对象定位的位置。本质上,热点只是一个空的游戏对象 - 一种放置标记。

如何使用它?

您所需要的只是对热点游戏对象的引用。您可以通过向为您跟踪它的极点游戏对象添加一个小脚本来做到这一点:

public class PowerPole : MonoBehaviour {
    public GameObject CrossArmsHotspot; // Set this in the inspector
}

然后您可以从任何电线杆实例中获取该热点参考,如下所示:

var targetHotspot = aPowerPoleGameObject.GetComponent<PowerPole>().CrossArmsHotspot;

那么这只是让您的目标对象使用您喜欢的任何技术将自己放置在该热点所在的位置的情况。如果你想让它“粘”在那里,那么:

void Start(){
   targetHotspot = aPowerPoleGameObject.GetComponent<PowerPole>().CrossArmsHotspot;
}

void Update(){
    transform.position = targetHotspot.transform.position;
}

将是一个(简化的)示例。

使用 lerp 向热点移动的更高级示例:

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

public class CrossArmsMover : MonoBehaviour
{
    public GameObject PowerPole;
    private GameObject targetHotspot;
    public GameObject CrossArms;
    public float TimeToTake = 5f;
    private float timeSoFar;
    private Vector3 startPosition;
    private Quaternion startRotation;


    // Start is called before the first frame update
    void Start()
    {
        startPosition = CrossArms.transform.position;
        startRotation = CrossArms.transform.rotation;
        targetHotspot = PowerPole.GetComponent<PowerPole>().CrossArmsHotspot;
    }

    // Update is called once per frame
    void Update()
    {
        timeSoFar+=Time.deltaTime;

        var progress = timeSoFar/TimeToTake;

        // Clamp it so it doesn't go above 1.
        if(progress > 1f){
            progress = 1f;
        }

        // Target position / rotation is..
        var targetPosition = targetHotspot.transform.position;
        var targetRotation = targetHotspot.transform.rotation;

        // Lerp towards that target transform:
        CrossArms.transform.position = Vector3.Lerp(startPosition, targetPosition, progress);
        CrossArms.transform.rotation = Quaternion.Lerp(startRotation, targetRotation, progress);

    }
}

【讨论】:

  • 我认为通过在对象上设置粘性行为是更简单的解决方案。
  • @loic.lopez 我已经添加了视觉效果以及实现这一点的代码:)
【解决方案2】:

您需要在以下游戏对象上放置一个脚本:

GameObject pitcher = //reference to the gameobject with the pitch;

const int DISTANCE_ON_LINE = //distance between the 2 objects

void Update() {
    transform.position = pitcher.transform.position + pitcher.transform.forward * DISTANCE_ON_LINE;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多