[英]Referencing Instantiated objects after their creation in Unity
你好!
在評論中與 Ruzihm 討論后。 我現在創建了一個簡單的游戲版本,以便更好地提出我遇到的問題。
現在的問題是,因為我無法手動創建與檢查器中的testObject
字段的連接。 我現在如何告訴 Unity 在游戲運行時使用我的實例化對象?
對於一次可能有 100 多個單元處於活動狀態的 RTS 游戲,這是否是一個很好的解決方案? 這里的最終目標是將這個力施加到 cursor 周圍的半徑上。 我正在考慮使用Physics.OverlapSphere
這是我所擁有的最小場景:
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.");
}
}
}
好吧,在我看來:
Unity使用ECS,意味着你的游戲object在你的游戲中是一個實體,它所包含的東西,比如Rigidbody
就是一個組件。 您附加到統一游戲對象的腳本也是此游戲對象中的一個組件
在ApplyForce
腳本中,您使用這些行
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;"); }
this.gameObject.GetComponent
,表示它會引用包含這個腳本的 Gameobject,並獲取名為 Rigidbody 的組件,並且你有一個方法叫做:使用 Rigidbody 向前推添加力在InputManager
class 中:
public GameObject testObject; public ApplyForce onSpawnTest; public Unit _unit; public ApplyForce applyForce; // Start is called before the first frame update void Start() { onSpawnTest = testObject.GetComponent<ApplyForce>(); } void Update() { if (Input.GetMouseButton(0)) { onSpawnTest.PushForward(); } }
GetComponent<>
時,onSpawnText 被分配給 testObject 中的一個組件,根據您的腳本,它是 ApplyForce 腳本組件。 而您只需使用 function PushForward。有什么不能理解的嗎? 給我一個評論
好吧,您正在創建 object 的新實例,但是您的輸入管理器會立即忘記它們(請注意,您對返回值不做任何事情)。 InputManager
只知道在其Start
中創建的ApplyForce
(然后根據鼠標輸入與其交互),而您的ApplyForce
腳本對任何InputManager
。 因此,只有第一個實例對鼠標輸入做出反應也就不足為奇了。
因此,必須對您的InputManager
和/或ApplyForce
做一些事情。 您的 InputManager 可以記住它創建的實例(這還不夠,因為例如,如果 map 觸發器創建新的玩家可控單位),或者它可以 go 每次都在尋找單位。
您的ApplyForce
可以在創建時向InputManager
注冊,但是您需要遍歷這些單元並找出哪些單元在鼠標下。
由於您只想根據 cursor 附近或下方的內容來查找 select ,並且僅在輸入發生時而不是像每一幀一樣,我會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 (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];
}
}
}
當然,這將要求您有興趣操縱的每個單元都有一個觸發對撞機。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.