如何在预制中设置变换变量的目标?

时间:2019-03-13 18:36:24

标签: unity3d

我已经为壳体制作了一个预制件,该壳体可以从发射器发射到空中,然后关闭屏幕,然后向下向下转到播放器转动时所在的位置。如何将播放器设置为其目标?

2 个答案:

答案 0 :(得分:1)

就像你说的那样。

预制件存在于资产中,而您根本无法在资产中具有场景引用。 (对于AnimatorController,同样存在一个问题)

但是,有很多方法可以在运行时获取引用。


ScriptableObject

使用ScriptableObject来存储参考,并在场景中有关Transform GameObject上具有相应的Setter组件。

[CreateAssetMenu(fileName = "TransformReference", menuName = "SceneReferences/Transform", order = 1)]
public class ScriptableTransformReference : ScriptableObject 
{
    public Transform value; 
}

在ProjectView(资产)中,进行鼠标右键单击-> 创建-> SceneReferences ->转换以创建新实例的ScriptableTransformReference

并且在您的播放器上没有这个二传手

// By adding ExecuteInEditMode this is already executed 
// without entering PlayMode
[ExecuteInEditMode]
public class TransformReferenceSetter : MonoBehaviour
{
    // Reference the created ScriptableObject here via the Inspector
    public ScriptableTransformReference TargetScriptableObject;

    private void Awake()
    {
        TargetScriptableObject.value = transform;
    }
}

比每次需要在另一个组件中引用时,只需再次创建一个字段

// Reference this in the Inspector
public ScriptableTransformReference SourceScriptableObject;

并访问value ..以确保在Start中使用,因此设置器Awake已被执行。这次,您{strong>可以在预制件中使用参考,因为ScriptableObject也位于资产中。


查找

您可以使用Find按名称获取对象并进行操作

var playerTransform = Find("Player").transform;

但我建议永远不要使用此..。它的性能很强,如果您更改GameObject的名称,它会破坏您的代码。它还仅适用于查找在执行时在层次结构中处于活动状态的GameObject。


FindObjectOfType

但是,如果仍然只有一名玩家,则在该玩家上创建一个专门的课程,例如

public class Player : MonoBehaviour {}

它不需要做任何事情。现在,您只需使用FindObjectOfType<Type>()即可获取其参考,从而更高效,更可靠

var playerTransform = FindObjectOfType<Player>().transform;

在场景中的任何其他组件中(例如,在实例化预制件之后)。 但是同样,它也仅在执行相应的GameObject和组件在层次结构中处于活动状态且已启用时才起作用。


单人

或者(ab)使用Singleton模式

public class Player : MonoBehaviour 
{
    public static Player Singleton;

    private void Awake ()
    {
        Singleton = this;
    }
}

并使用

var playerTransform = Player.Singleton.transform;

其他任何地方。


依赖注入

您可能想进入Zenject或类似种类的依赖项注入。尽管设置起来比较完善,但是一旦它开始工作,它就是一个非常强大的工具,即使在各种场景和基于上下文的环境下也可以提供引用。

答案 1 :(得分:0)

使用弹丸运动

这不是一个完整的答案,您只需更改内容即可解决问题,这很有趣。

var pos = Vector3.MoveTowards(transform.position, _target.transform.position , _projectileSpeed * Time.deltaTime);
  rigidbody.MovePosition(pos);

尝试使用transform.LookAt(targetXZPos);使外壳尖端指向目标。

如果此代码未提供所需的输出,则应考虑 启动速度, 发射角度 到目标的距离 并使射弹公式变强一点,但是会创造更多的独创性,并且会给玩家带来更多有趣的尝试角度的感觉(如果需要),发射速度可以保持恒定基于不同的炮弹(向玩家出售不同范围的炮弹也是一个好主意)。