foo cannot be accessed from within thing.Begin()
But I think I can solve this by creating a reference when thing is initialized.
But the harder problem is with Invoke:
2) thing.End() cannot be called from within thing.End
I’d like to call thing.Begin() from outside the class without knowing ahead of time what this instance of thing will evaluate during Begin - that’s for thing to track.
public class MyScript : MonoBehaviour {
public bool foo;
public MyClass thing;
public class MyClass {
public bool bar;
public float endTime;
public void Begin () {
if ( foo && bar ) {
Invoke( "End", endTime );
}
}
public void End () {
// stuff specific to this instance of thing
}
}
}
this is because foo is a field (variable) in the class MyScript. MyClass is a nested class inside of MyScript so it doesn’t have access to any of the MyScript variables. You can give it access by providing it a hook in a constructor like this:
Fix to Problem 1
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyScript : MonoBehaviour
{
public bool foo;
public MyClass thing;
void Awake()
{
thing = new MyClass(this);
}
public class MyClass
{
public bool bar;
public float endTime;
private MyScript parent;
//default constructor
public MyClass()
{ }
// constructor to know about parent
public MyClass(MyScript parent)
{
this.parent = parent;
}
public void Begin()
{
if (parent.foo && bar)
{
Invoke("End", endTime);
}
}
public void End()
{
// stuff specific to this instance of thing
}
}
}
This is because MyClass is not a Monobehaviour. Your best bet is to return endTime back to MyScript and have it Inovoke a function that calls End of MyClass like this:
FIx to Problem 2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyScript : MonoBehaviour
{
public bool foo;
public MyClass thing;
void Awake()
{
thing = new MyClass(this);
}
public void Begin()
{
if (thing.Begin())
Invoke("End", thing.endTime);
}
private void End()
{
thing.End();
}
public class MyClass
{
public bool bar;
public float endTime;
private MyScript parent;
//default constructor
public MyClass()
{ }
// constructor to know about parent
public MyClass(MyScript parent)
{
this.parent = parent;
}
public bool Begin()
{
return parent.foo && bar;
}
public void End()
{
// stuff specific to this instance of thing
}
}
}
With this setup you just need someone to call MyScript from outside of it with its public Begin method. There are lots of ways to get hooks to other GameObjects. You can have another script have a public GameObject variable that you set in the inspector:Finding another GameObject in the Inspector
public class AnotherScript : MonoBehaviour
{
// Set this in the inspector by dragging the other GameObject
// onto this in the inspector
public GameObject other;
void Start()
{
MyScript otherScript = other.GetComponent<MyScript>();
otherScript.Begin();
}
}
Or you can use a tag to find the other script, you would need to Tag the GameObject that has MyScript attached with a specific tag in the Inspector.
Finding an object with a Tag.
public class AnotherScript : MonoBehaviour
{
void Start()
{
GameObject other = GameObject.FindWithTag("YourTag");
MyScript otherScript = other.GetComponent<MyScript>();
otherScript.Begin();
}
}
Note the solutions to 1 and 2 are how you would achieve your solution with the correct syntax. Though depending on what your actually after they may not be the best ways to go about it. With the setup I showed the variables are intertwined between the classes and maybe you could just restructure it into one class.
You solution to problem 1 is essentially what I figured.
For number 2, I don’t need to access thing.Begin() from outside of MyScript (at least not yet). But your explanation of Invoke needing the class to be a MonoBehaviour makes sense.
I’ll probably have to move the evaluation routine outside of MyClass, accessing the fields inside it.
I was trying for a cleaner and more organized code style, but it didn’t apply well in this case.