【问题标题】:Unity: An object reference is required to access non-static member - Ray cast to GameObjectUnity:访问非静态成员需要对象引用 - Ray cast to GameObject
【发布时间】:2015-04-29 20:08:07
【问题描述】:

我正在制作一款 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;
    }
    }
    }

提前致谢! =)

【问题讨论】:

  • 不要在与 Unity3d 游戏引擎相关的问题中使用统一标签。有 unity3d 标签。
  • 抱歉,我没有意识到

标签: c# unity3d raycasting gameobject playmaker


【解决方案1】:

尽管 Christos 对 why 的看法是正确的,但它会引发异常(您尝试访问实例方法,就好像它是静态方法一样),但他遗漏了一个细节。

在 Unity3D 中,您不能(轻松)实例化实现 MonoBehaviour 的类。您可以通过将脚本组件附加到现有游戏对象来创建它们,然后您可以在代码中引用它们。

所以要解决这个问题,如果你想调用那个方法,你必须首先获得对场景中附加脚本组件的引用,然后你才能做到。

简单示例,假设脚本组件 Unit 附加到同一个 GameObject,您可以这样引用它:

Unit unit = GetComponent<Unit>();
// now we can call instance fields/properties/methods on this specific instance!

【讨论】:

    【解决方案2】:

    从你得到的报错信息中,很明显是方法

    SetOurObject(UnityEngine.RaycastHit)

    不是Unit 类的static 方法。

    因此,你首先要创建这个类的一个实例,然后调用这个方法。

    // 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);
    

    【讨论】:

    • 感谢您的快速回复,请原谅我的菜鸟,但您能用蹩脚的话解释一下吗? Unit 类实现了什么?
    • 欢迎你,伙计。根本不是问题。当然,据我了解,SetOurObjectUnit 类的一种方法。正确的?如果是这样,看起来是这样,并且鉴于它不是 static 方法,您可以这样使用它:Static.SetOurObject(UnityEngine.RaycastHit),就像我们在 Console 类的 WriteLine 方法的情况下所做的那样,@ 987654332@。我们首先要创建一个Unit 类的实例,然后在这个对象上调用这个方法。现在更清楚了吗?
    • 好的,这有帮助,谢谢.. 但它没有帮助.. vector3 函数“GetDestination”可以是动态函数而不是静态函数吗?如何?我认为问题在于静态函数不允许我将命中转换为游戏对象..
    • @JaredBrandjes c# 中的方法属于类的实例或类。在第一种情况下,它被称为实例方法,可以像我上面指出的那样使用。而在第二种情况下,它是一个静态方法,可以使用,只需使用类名称点方法名称ClassName.Method()。据我所知,没有任何动态方法的概念。因此,如果您的问题是您是否可以将 GetDestinationstatic 更改为非静态的实例方法,我的答案是肯定的。只要符合您的需要,您就可以这样做。
    猜你喜欢
    • 2023-03-30
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 2014-11-04
    相关资源
    最近更新 更多