你好!
在評論中與 Ruzihm 討論之后。我現在已經創建了我的游戲的一個簡單版本,以便更好地提出我遇到的問題。
現在的問題是,因為我無法testObject在檢查器中手動創建與該欄位的連接。我現在如何告訴 Unity 在游戲運行時使用我的實體化物件?
對于一次可能有 100 多個單位處于活動狀態的 RTS 游戲,這是否是一個很好的解決方案?此處的最終目標是將此力應用于游標周圍的半徑。我正在考慮使用Physics.OverlapSphere
這是我所擁有的最小場景:
- 新的 Unity 場景
- 將 InputManager 附加到主攝像頭。
- 創建了一個膠囊和一架飛機。
- 將 ApplyForce 添加到 Capsule
- 從膠囊創建一個預制件并將其從場景中洗掉。
- 在 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.");
}
}
}
uj5u.com熱心網友回復:
好吧,您正在創建物件的新實體,但是您的輸入管理器會立即忘記它們(請注意,您對回傳值沒有做任何事情)。該InputManager只知道的ApplyForce是在其創建Start(然后它根據滑鼠輸入互動)和你的ApplyForce腳本一無所知任何InputManager。因此,只有第一個實體對滑鼠輸入做出反應也就不足為奇了。
因此,必須對您InputManager和/或您的ApplyForce. 您InputManager可以記住它創建的實體(這還不夠,因為例如,地圖觸發器創建了新的玩家可控單位)或者它每次都可以去尋找單位。
您ApplyForce可以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];
}
}
}
當然,這將要求您有興趣操作的每個單元都有一個觸發器對撞機。
uj5u.com熱心網友回復:
好吧,在我看來:
Unity 使用 ECS,這意味著你的游戲中的游戲物件是一個物體,而它包含的東西,例如,
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."); }- 這意味著您將獲得具有此腳本的 Gameobject 中的“Rigidbody”組件。GetComponent 方法等于
this.gameObject.GetComponent,這意味著它將參考包含此腳本的 Gameobject,并獲取名為 Rigidbody 的組件,并且您有一個名為 : push forward 以使用 Rigidbody 添加力的方法
- 這意味著您將獲得具有此腳本的 Gameobject 中的“Rigidbody”組件。GetComponent 方法等于
在
InputManager課堂上: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(); } }- 您將參考在第一行代碼中宣告的游戲物件。
- onSpawnText 具有 ApplyForce 類的型別,您已在以下腳本中宣告
- 當您使用時
GetComponent<>,onSpawnText 被分配給 testObject 中的一個組件,根據您的腳本,它是 ApplyForce 腳本組件。您只需使用 PushForward 功能。
有什么你不能理解的嗎?給我一個評論
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/387897.html
