在 Unity 中创建后引用实例化对象
Posted
技术标签:
【中文标题】在 Unity 中创建后引用实例化对象【英文标题】:Referencing Instantiated objects after their creation in Unity 【发布时间】:2022-01-20 01:45:01 【问题描述】:嗨!
在 cmets 与 Ruzihm 讨论之后。我现在创建了一个简单的游戏版本,以便更好地提出我遇到的问题。
现在的问题是,因为我无法在检查器中手动创建与 testObject
字段的连接。我现在如何告诉 Unity 在游戏运行时使用我的实例化对象?
对于一次可能有 100 多个单元处于活动状态的 RTS 游戏来说,这是一个好的解决方案吗?这里的最终目标是将这个力施加到光标周围的半径上。我正在考虑使用Physics.OverlapSphere
这是我所拥有的最小场景:
-
新的 Unity 场景
将 InputManager 附加到主摄像头。
创建了一个太空舱和一架飞机。
为 Capsule 添加了 ApplyForce
从胶囊中创建了一个预制件并将其从场景中删除。
在 InputManager 中,我添加了按空格键来实例化带有 ApplyForce 脚本的胶囊的功能..
将胶囊预制件拖到 InputManager "objectToGenerate"
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GL.RTS.Mites
public class InputManager : MonoBehaviour
public GameObject testObject;
public ApplyForce onSpawnTest;
public GameObject objectToGenerate;
void Start()
onSpawnTest = testObject.GetComponent<ApplyForce>();
void Update()
if(Input.GetKeyDown(KeyCode.Space))
Instantiate(objectToGenerate);
if (Input.GetMouseButton(0))
onSpawnTest.PushForward();
我附加到 Capsule 的 ApplyForce 脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GL.RTS.Mites
public class ApplyForce : MonoBehaviour
public float moveSpeed;
Rigidbody rb;
void Start()
rb = GetComponent<Rigidbody>();
Debug.Log("A Mite has spawned!");
public void PushForward()
rb.AddRelativeForce(Vector3.up * moveSpeed * Time.deltaTime);
Debug.Log("A force of: " + moveSpeed + " is being added.");
【问题讨论】:
这段代码是哪种编程语言?:C# 还是 UnityScript?对我来说它看起来像 C#,但你已经标记了两者。 这是c#,抱歉我会删除UnityScript标签 您要移动的对象是初始场景的一部分还是稍后生成的?如果稍后,InputManager.Start
方法可能会在生成对象实例化之前运行。
你是对的@Ruzihm,我尝试创建一个全新的 Unity 场景,将 InputManager 连接到主摄像头。创造了一个胶囊和一架飞机。将 ApplyForce 添加到 capsule,并在检查器中将 capsule 引用到 InputManager 的“testObject”。增加了一吨的力量,我确实开始飞了!这是一个很好的原因,然后我知道这不是代码的问题!我的问题是我的“真实”Unity场景中的“testObject”没有正确引用实例。所以我需要弄清楚在创建实例后如何引用它。
@Ruzihm,我终于有时间更新问题以更好地反映我的问题。我想我知道我要在代码中做什么,但是由于我在 C# 方面的经验有限,我无法引用正确的对象来增加力量。任何帮助都是极好的!我也愿意接受建议,因为我不知道这种方法是否能很好地扩展:)
【参考方案1】:
好吧,您正在创建对象的新实例,但是您的输入管理器立即忘记了它们(请注意,您对返回值什么都不做)。 InputManager
只知道在其Start
中创建的ApplyForce
(然后根据鼠标输入与其交互),而您的ApplyForce
脚本对任何InputManager
一无所知。因此,只有第一个实例对鼠标输入做出反应也就不足为奇了。
因此,必须对您的InputManager
和/或您的ApplyForce
做一些事情。您的 InputManager
可以记住它创建的实例(这还不够,因为例如,如果地图触发器创建新的玩家可控单位会怎样)或者它可以每次都去寻找单位。
您的ApplyForce
可以在创建InputManager
时注册它们,但是您需要遍历这些单元并找出鼠标下的单元。
由于您只想根据光标附近或光标下的内容进行选择,并且仅在输入发生时而不是像每一帧一样,我会采用最简单的方法,让您的 InputManager
在需要时找到单位他们。如下所示,在 cmets 中进行解释:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GL.RTS.Mites
public class InputManager : MonoBehaviour
public GameObject testObject;
public ApplyForce onSpawnTest;
public GameObject objectToGenerate;
private Camera mainCam;
// which layers to consider for cursor detection
[SerializeField] LayerMask cursorLayerMask;
// how big for cursor detection
[SerializeField] float cursorRadius;
void Awake()
// cache main camera
mainCam = Camera.main;
void Update()
if(Input.GetKeyDown(KeyCode.Space))
Instantiate(objectToGenerate);
if (Input.GetMouseButton(0))
Collider[] colls = FindCollidersUnderCursor();
// check each collider for an applyforce and use it if present
foreach( Collider coll in colls)
ApplyForce af = coll.GetComponent<ApplyForce>();
if (af != null)
af.PushForward();
Collider[] FindCollidersUnderCursor()
// find ray represented by cursor position on screen
// and find where it intersects with ground
// This technique is great for if your camera can change
// angle or distance from the playing field.
// It uses mathematical rays and plane, no physics
// calculations needed for this step. Very performant.
Ray cursorRay = mainCam.ScreenPointToRay(Input.mousePosition);
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
if (groundPlane.Raycast(cursorRay, out float cursorDist))
Vector3 worldPos = cursorRay.GetPoint(cursorDist);
// Check for triggers inside sphere that match layer mask
return Physics.OverlapSphere(worldPos, cursorRadius,
cursorLayerMask.value, QueryTriggerInteraction.Collide);
// if doesn't intersect with ground, return nothing
return new Collider[0];
当然,这将要求您有兴趣操纵的每个单位都有一个触发对撞机。
【讨论】:
我会投赞成票,但距离这样做还有 2 分。有机会我会回来的!无论如何,谢谢一百万!这给了我很多工作。我知道我的问题很混乱,但我从像这样缩小范围中学到了很多东西。对撞机的技巧太棒了!我喜欢为你的射线创建一个虚拟地面的想法。并且您将 OverlapSphere 的实现作为一个不错的奖励,这终于有意义了。以上是关于在 Unity 中创建后引用实例化对象的主要内容,如果未能解决你的问题,请参考以下文章