Andrew Magnuson
Andrew Magnuson

Reputation: 13

Variable across multiple classes

I'm trying to learn C#, but I'm having some problems with creating a variable across classes in Unity.

Node Class:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Node {

    public Vector3 dimensions;
    public int jointType;
    public Vector2 jointLimit;
    public int recursiveLimit;
    public int nodeId;
    public List<int> to;
    public int fro;



    public Node (Vector3 dim, int jointT, Vector2 jointL, int recLim, int id){
        dimensions = dim;
        jointType = jointT;
        jointLimit = jointL;
        recursiveLimit = recLim;
        nodeId = id;
    }
}

Connection Class:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Connection {

    public Vector3 position;
    public Vector3 orientation;
    public float scale;
    public int reflection;
    public bool terminalOnly;
    public int[] to;
    public int fro;


    public Connection (Vector3 pos, Vector3 orien, float scl, int refl, bool term, int[] to, int fro){
        position = pos;
        orientation = orien;
        scale = scl;
        reflection = refl;
        terminalOnly = term;
        this.to = to;
        this.fro = fro;
    }

}

I'm trying to have a Node variable and a Connection variable that are both accessible by the GenoManager class and the BodyPart class (which there will be many of).

BodyPart class:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BodyPart : MonoBehaviour {

    public BodyPart block;
    public bool finished;
    //Initialization
    void Start () {
        finished = false;

    }

    //Generation of all blocks [incomplete]
    void Update () {
        while (!finished) {
            BodyPart newPart = Instantiate (block, transform.position + Vector3(0,10,0), transform.rotation) as BodyPart;
        newPart.transform.localScale = p.nodes[0].dimensions; //This line also has the error CS0119
//This line has the error CS0176
            //Trying to Scale by the dimensions (a Vector3) of the 
first Node in the nodes array



            finished = true;
        }
    }
}

GenoManager Class:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class GenoManager : MonoBehaviour {


    public BodyPart block;
    public Transform pos;


    // Update is called once per frame
    void Update () {

    }

    public static List<Node> nodes = new List<Node> ();
    Node t = new Node (new Vector3(1,4,1), 1, Vector2.up, 2, 0);
    static int[] testList = { 1, 2 };

    public static Connection te = new Connection (Vector3.up, Vector3.up, 1.5f, 1, false, testList,0); 

    void Start(){
        //Node Test Generation
        nodes.Add(t);
        print (nodes [0]);

        //Root Block Generation
        BodyPart newPart = Instantiate (block, pos.position, pos.rotation) as BodyPart;
        newPart.transform.localScale = nodes[0].dimensions;
    }
}

Basically what I'm asking is, how would I go about making a variable that can be created in one class and viewed by other classes? (Also, sorry if the formatting is off, this is my first time posting on StackOverflow.)

Thanks in advance.

Upvotes: 1

Views: 3246

Answers (2)

Erik Philips
Erik Philips

Reputation: 54638

Variable that can be ... viewed by other classes?

In C# variables are really defined within a class. You don't pass them around. You can pass around a Class or a Struct that have public properties (don't use public fields) that hold values.

how would I go about making a variable that can be created in one class and viewed by other classes?

Ideally you want to use Dependency inversion principle. That is to say that if class A requires access to a value (dependency) for it to function at any point in time, you should pass it as part of the constructor. Ideally, you would construct class B (the dependency) which would implement an interface that gives only the necessary properties/methods/access needed for other classes (class A). For example:

static Main()
{
  var person = new Person { Age = 21 };
  var bartender = new Bartender(person);

  if (bartender.CanServeAlcohol())
  {
  }
}

public interface ICustomer
{
  int Age { get; } 
  // Ideally this should be a DateTime with a function
  // that returns the age, so this is really just an example
}

public class Customer : ICustomer
{
  public int Age { get; set; }
}

public class Bartender
{
  public ICustomer _customer;

  public Bartender(ICustomer customer)
  {
    _customer = customer;
  }

  public bool CanServeAlcohol()
  {
    return _customer.Age >= 21;
  }
}

In this example, the Customer is created, but only what is needed via the Interface is available. The Bartender now has access to the Customer but doesn't have access to change the Age. Since Bartender requires a customer to be created, you can't accidentally not include a Customer when creating one.

Once you understand this principle, I highly recommend looking into Dependency Injection Frameworks which can do these things for you automatically. Popular frameworks I am familiar with are Autofac, Unity, Ninject, StructureMap.. etc. There are many other and they all pretty much do the same thing.

(realize this isn't the best example, because a real bartender can serve more than one person, but it works for your example)

I HIGHLY RECOMMEND you don't use Static Fields. There are many many issues with them (threading can be a serious issue, they tend to become god objects and make it harder to implement extensionibility).

Upvotes: 1

Duncanmhor
Duncanmhor

Reputation: 43

You'd use a public static variable https://unity3d.com/learn/tutorials/topics/scripting/statics

using System;
public class ContainsStaticVariable
{
    public static string ExampleStaticVariable = "I am the value of a static variable";
}

public class DisplayContentsOfStaticVariable
{
    public static void Main()
    {
        Console.WriteLine(ContainsStaticVariable.ExampleStaticVariable);
        Console.WriteLine("Press return to exit...");
        Console.ReadLine();
    }
}

If you don't want the value to be changed at runtime, you can use public const

Upvotes: 0

Related Questions