在Unity中创建实例化对象后引用它们

Referencing Instantiated objects after their creation in Unity(在Unity中创建实例化对象后引用它们)
本文介绍了在Unity中创建实例化对象后引用它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨!

在评论中与Ruzihm讨论之后。我现在已经创建了我的游戏的一个简单版本,以便更好地提出我的问题。 现在的问题是,因为我无法手动创建到检查器中testObject字段的连接。现在如何告诉Unity在游戏运行时使用我的实例化对象?

对于一次可能有100个活动单位的RTS游戏来说,这是一个很好的解决方案吗?这里的最终目标是将此力应用于光标周围的半径。我正在考虑使用Physics.OverlapSphere

以下是我所拥有的最小方案:

  1. 新建Unity场景
  2. 已将InputManager连接到主摄像机。
  3. 创建了一个胶囊和一个平面。
  4. 已将ApplyForce添加到胶囊中
  5. 从胶囊创建预制件并将其从场景中删除。
  6. 在InputManager中,我添加了按空格键实例化带有ApplyForce脚本的胶囊的功能。
  7. 将胶囊预制拖到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();
            }
        }
    }
}

我附加到胶囊的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.");
        }
    }
}

推荐答案

好的,您正在创建对象的新实例,但是您的输入管理器立即忘记了它们(请注意,您没有对返回值做任何操作)。InputManager只知道在其Start中创建的ApplyForce(然后根据鼠标输入与其交互),而您的ApplyForce脚本对任何InputManager一无所知。因此,只有第一个实例对鼠标输入做出反应就不足为奇了。

因此,必须对您的InputManager和/或您的ApplyForce执行某些操作。您的InputManager可以记住它创建的实例(这是不够的,因为例如,如果地图触发器创建了新的玩家可控单位怎么办),或者它可以每次都去查找单位。

您的ApplyForce可以在创建InputManager时注册到InputManager,但之后您需要遍历这些单元并找出鼠标下面有哪些单元。

由于您只想根据光标附近或下方的位置选择单位,并且仅当输入发生时才选择单位,而不是像每个框架一样,因此我将采用最简单的方法,只需让InputManager在需要时查找单位即可。如下所示,在评论中说明:

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];
        }
    }
}

当然,这将要求您感兴趣的每个单元都有触发对撞器。

这篇关于在Unity中创建实例化对象后引用它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)