Unity:需要对象引用才能访问非静态成员 - 光线投射到 GameObject
Unity: An object reference is required to access non-static member - Ray cast to GameObject
我正在制作一款 RTS 风格的游戏,但遇到了一个错误。
我正在尝试将当前选定的单元(脚本所在的对象)发送到光线投射命中的对象的 Playmaker FSM。我意识到您无法在静态函数内部访问游戏对象和转换,因此我尝试调用另一个函数来使用命中并填充游戏对象变量。
这是错误:
Assets/Scripts/Unit.cs(57,41): error CS0120: An object reference is required to access non-static member `Unit.SetOurObject(UnityEngine.RaycastHit)'
我认为主要问题在这里:
public static Vector3 GetDestination()
{
if (moveToDestination == Vector3.zero)
{
RaycastHit hit;
Ray r = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(r, out hit))
{
while (!passables.Contains(hit.transform.gameObject.name))
{
if (!Physics.Raycast(hit.transform.position, r.direction, out hit)) //point + r.direction * 0.1f
break;
}
//gameObject.GetComponent<NavMeshAgent>().SetDestination(hit.point);
//if (hit.transform != null){
//print (hit);
if (resources.Contains(hit.transform.gameObject.name)){
SetOurObject(hit);
//SelectedUnit.Value = GameObject.name;
//ResourceHit.Fsm.Event("startHit");
} else {
moveToDestination = hit.point;
}
//}
}
}
return moveToDestination;
}
public void SetOurObject(RaycastHit hitRay)
{
ourObject = hitRay.transform.gameObject;
PlayMakerFSM ourFSM = ourObject.GetComponent<PlayMakerFSM>();
FsmGameObject SelectedUnit = ourFSM.FsmVariables.GetFsmGameObject("SelectedUnit");
SelectedUnit.Value = new GameObject();
ourFSM.Fsm.Event("ResourceHit");
}
这是整个脚本:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using HutongGames.PlayMaker;
public class Unit : MonoBehaviour {
public PlayMakerFSM ResourceHit;
public GameObject ourObject;
public bool selected = false;
private Color SelectedCol = new Color(0.114f, 0.22f, 0.039f, 1.0f);
private Color UnselectedCol = new Color(0.357f, 0.604f, 0.184f, 1.0f);
private bool selectedByClick = false;
private Vector3 moveToDest = Vector3.zero;
private static Vector3 moveToDestination = Vector3.zero;
private static List<string> passables = new List<string>() { "Floor" };
private static List<string> resources = new List<string>() { "Res_Wood" };
// Update is called once per frame
private void CleanUp()
{
if (!Input.GetMouseButtonUp(1))
moveToDestination = Vector3.zero;
}
private NavMeshAgent agent;
void Start() {
agent = GetComponent<NavMeshAgent>();
}
public static Vector3 GetDestination()
{
if (moveToDestination == Vector3.zero)
{
RaycastHit hit;
Ray r = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(r, out hit))
{
while (!passables.Contains(hit.transform.gameObject.name))
{
if (!Physics.Raycast(hit.transform.position, r.direction, out hit))
break;
}
if (resources.Contains(hit.transform.gameObject.name)){
SetOurObject(hit);
} else {
moveToDestination = hit.point;
}
}
}
return moveToDestination;
}
public void SetOurObject(RaycastHit hitRay)
{
ourObject = hitRay.transform.gameObject;
PlayMakerFSM ourFSM = ourObject.GetComponent<PlayMakerFSM>();
FsmGameObject SelectedUnit = ourFSM.FsmVariables.GetFsmGameObject("SelectedUnit");
SelectedUnit.Value = new GameObject();
ourFSM.Fsm.Event("ResourceHit");
}
void Update () {
CleanUp();
if (this.GetComponent<Renderer>().isVisible && Input.GetMouseButton(0))
{
if (!selectedByClick){
Vector3 camPos = Camera.main.WorldToScreenPoint(transform.position);
camPos.y = CameraOperator.InvertMouseY (camPos.y);
selected = CameraOperator.selection.Contains(camPos);
}
if (selected)
this.GetComponent<Renderer> ().material.color = UnselectedCol;
else
this.GetComponent<Renderer> ().material.color = SelectedCol;
}
if (selected && Input.GetMouseButtonUp(1))
{
Vector3 destination = GetDestination();
if (destination != Vector3.zero)
{
gameObject.GetComponent<NavMeshAgent>().SetDestination(destination); //all you need if you have unity pro
//moveToDest = destination;
//moveToDest.y += floorOffset;
}
}
}
private void OnMouseDown()
{
selectedByClick = true;
selected = true;
}
private void OnMouseUp()
{
if (selectedByClick)
selected = true;
selectedByClick = false;
}
}
}
提前致谢! =)
从你得到的错误信息来看,很明显方法
SetOurObject(UnityEngine.RaycastHit)
不是 class Unit
的 static
方法。
因此,您首先要创建此 class 的实例,然后再调用此方法。
// I don't know exactly the signature of the constructor class
// If it is parameterless or not etc.
// So you have to correct it correspondingly, If I am wrong.
var unit = new Unit();
然后你就可以调用这个对象的方法了。
unit.SetOurObject(UnityEngine.RaycastHit);
尽管 Christos 关于 why
抛出异常的说法是正确的(您正在尝试访问实例方法,就好像它是静态方法一样),但他遗漏了一个细节。
在 Unity3D 中,您无法(轻松地)实例化 类 实现 MonoBehaviour。您可以通过将脚本组件附加到现有游戏对象来创建它们,然后您可以在代码中引用它们。
所以要解决这个问题,如果你想调用那个方法,你必须首先获得对场景中附加脚本组件的引用,然后你才能这样做。
简单示例,假设脚本组件 Unit 附加到同一个 GameObject,您可以这样引用它:
Unit unit = GetComponent<Unit>();
// now we can call instance fields/properties/methods on this specific instance!
我正在制作一款 RTS 风格的游戏,但遇到了一个错误。 我正在尝试将当前选定的单元(脚本所在的对象)发送到光线投射命中的对象的 Playmaker FSM。我意识到您无法在静态函数内部访问游戏对象和转换,因此我尝试调用另一个函数来使用命中并填充游戏对象变量。
这是错误:
Assets/Scripts/Unit.cs(57,41): error CS0120: An object reference is required to access non-static member `Unit.SetOurObject(UnityEngine.RaycastHit)'
我认为主要问题在这里:
public static Vector3 GetDestination()
{
if (moveToDestination == Vector3.zero)
{
RaycastHit hit;
Ray r = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(r, out hit))
{
while (!passables.Contains(hit.transform.gameObject.name))
{
if (!Physics.Raycast(hit.transform.position, r.direction, out hit)) //point + r.direction * 0.1f
break;
}
//gameObject.GetComponent<NavMeshAgent>().SetDestination(hit.point);
//if (hit.transform != null){
//print (hit);
if (resources.Contains(hit.transform.gameObject.name)){
SetOurObject(hit);
//SelectedUnit.Value = GameObject.name;
//ResourceHit.Fsm.Event("startHit");
} else {
moveToDestination = hit.point;
}
//}
}
}
return moveToDestination;
}
public void SetOurObject(RaycastHit hitRay)
{
ourObject = hitRay.transform.gameObject;
PlayMakerFSM ourFSM = ourObject.GetComponent<PlayMakerFSM>();
FsmGameObject SelectedUnit = ourFSM.FsmVariables.GetFsmGameObject("SelectedUnit");
SelectedUnit.Value = new GameObject();
ourFSM.Fsm.Event("ResourceHit");
}
这是整个脚本:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using HutongGames.PlayMaker;
public class Unit : MonoBehaviour {
public PlayMakerFSM ResourceHit;
public GameObject ourObject;
public bool selected = false;
private Color SelectedCol = new Color(0.114f, 0.22f, 0.039f, 1.0f);
private Color UnselectedCol = new Color(0.357f, 0.604f, 0.184f, 1.0f);
private bool selectedByClick = false;
private Vector3 moveToDest = Vector3.zero;
private static Vector3 moveToDestination = Vector3.zero;
private static List<string> passables = new List<string>() { "Floor" };
private static List<string> resources = new List<string>() { "Res_Wood" };
// Update is called once per frame
private void CleanUp()
{
if (!Input.GetMouseButtonUp(1))
moveToDestination = Vector3.zero;
}
private NavMeshAgent agent;
void Start() {
agent = GetComponent<NavMeshAgent>();
}
public static Vector3 GetDestination()
{
if (moveToDestination == Vector3.zero)
{
RaycastHit hit;
Ray r = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(r, out hit))
{
while (!passables.Contains(hit.transform.gameObject.name))
{
if (!Physics.Raycast(hit.transform.position, r.direction, out hit))
break;
}
if (resources.Contains(hit.transform.gameObject.name)){
SetOurObject(hit);
} else {
moveToDestination = hit.point;
}
}
}
return moveToDestination;
}
public void SetOurObject(RaycastHit hitRay)
{
ourObject = hitRay.transform.gameObject;
PlayMakerFSM ourFSM = ourObject.GetComponent<PlayMakerFSM>();
FsmGameObject SelectedUnit = ourFSM.FsmVariables.GetFsmGameObject("SelectedUnit");
SelectedUnit.Value = new GameObject();
ourFSM.Fsm.Event("ResourceHit");
}
void Update () {
CleanUp();
if (this.GetComponent<Renderer>().isVisible && Input.GetMouseButton(0))
{
if (!selectedByClick){
Vector3 camPos = Camera.main.WorldToScreenPoint(transform.position);
camPos.y = CameraOperator.InvertMouseY (camPos.y);
selected = CameraOperator.selection.Contains(camPos);
}
if (selected)
this.GetComponent<Renderer> ().material.color = UnselectedCol;
else
this.GetComponent<Renderer> ().material.color = SelectedCol;
}
if (selected && Input.GetMouseButtonUp(1))
{
Vector3 destination = GetDestination();
if (destination != Vector3.zero)
{
gameObject.GetComponent<NavMeshAgent>().SetDestination(destination); //all you need if you have unity pro
//moveToDest = destination;
//moveToDest.y += floorOffset;
}
}
}
private void OnMouseDown()
{
selectedByClick = true;
selected = true;
}
private void OnMouseUp()
{
if (selectedByClick)
selected = true;
selectedByClick = false;
}
}
}
提前致谢! =)
从你得到的错误信息来看,很明显方法
SetOurObject(UnityEngine.RaycastHit)
不是 class Unit
的 static
方法。
因此,您首先要创建此 class 的实例,然后再调用此方法。
// I don't know exactly the signature of the constructor class
// If it is parameterless or not etc.
// So you have to correct it correspondingly, If I am wrong.
var unit = new Unit();
然后你就可以调用这个对象的方法了。
unit.SetOurObject(UnityEngine.RaycastHit);
尽管 Christos 关于 why
抛出异常的说法是正确的(您正在尝试访问实例方法,就好像它是静态方法一样),但他遗漏了一个细节。
在 Unity3D 中,您无法(轻松地)实例化 类 实现 MonoBehaviour。您可以通过将脚本组件附加到现有游戏对象来创建它们,然后您可以在代码中引用它们。
所以要解决这个问题,如果你想调用那个方法,你必须首先获得对场景中附加脚本组件的引用,然后你才能这样做。
简单示例,假设脚本组件 Unit 附加到同一个 GameObject,您可以这样引用它:
Unit unit = GetComponent<Unit>();
// now we can call instance fields/properties/methods on this specific instance!