I'm making an RTS style game and i've got an error. I'm trying to send the current selected unit (the object the script is on) to the Playmaker FSM of the object the raycast hit. I realised that you cannot access gameobjects and transforms inside of a static function so I tried to call another function to use the hit and fill the gameobject variable.
This is the error:
Assets/Scripts/Unit.cs(57,41): error CS0120: An object reference is required to access non-static member `Unit.SetOurObject(UnityEngine.RaycastHit)'
The main issue I think is here:
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");
}
And here is the whole script:
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;
}
}
}
Thanks in advance! =)
Even though Christos is right about why
it throws an exception (you're trying to access an instance method as if it was a static method), he's missing one detail.
In Unity3D you can't instantiate (easily) classes that implement MonoBehaviour. You create them by attaching a script component to existing gameobjects and then you can reference them in the code.
So to solve this, if you want to call that method, you have to first get a reference to the attached script component that's in the Scene and then you can do it.
Simple example, let's say the script component Unit is attached to the same GameObject, you reference it like this:
Unit unit = GetComponent<Unit>();
// now we can call instance fields/properties/methods on this specific instance!