Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by BurningKrome · Feb 16, 2015 at 08:18 AM · variablesreference-other-object

C#: Create a variable placeholder for an unknown script

I've seen this question asked, and the answer seems to be that it can't be done...but it's such a common thing to do in other languages I'm surprised. So, maybe I'm misunderstanding something.

I'm creating a molecular simulation game. It will have lots of atoms with basically all the same functions, but needing different parameters.

It seems the best way to do this (and avoid necessary code duplications) is to write a general "nucleus.cs" script with the action methods, which access a "characteristics.cs" script to determine these parameters.

But there seems no way to attach different (unknown or differently named) scripts to the variable because of C#'s restrictive casting.

I.e.... the plan:

(This script goes on ALL atoms)

 public class NucleusScript : MonoBehaviour {

     // External object references
     public IdontKnowWhatToPutHere characteristics;


     public void reactWithHydrogen(){
          if (distance < characteristics.electronegativity){
              // make boom and stuff
          }
 }//end class

(OxygenCharacteristic.cs)

 public class OxygenCharacteristics : MonoBehaviour {

     float ELECTRONEGATIVITY = 3.44; 

     public float electronegativity {
         get {return ELECTRONEGATIVIY;}
         SET {throw new error you can't do this yadda};
     } 
 }//class

(NitrogenCharacteristic.cs)

 public class NitrogenCharacteristic : MonoBehaviour {

     float ELECTRONEGATIVITY = 3.04; 

     public float electronegativity {
         get {return ELECTRONEGATIVIY;}
         SET {throw new error you can't do this yadda};
     }
 )//class

Then, in unity editor, the nucleus script is dragged to ALL the different atom objects (I.e. Oxygen, Nitrogen, etc)...with this "characteristics" variable placeholder.

THEN, also in unity editor, the script "OxygenCharacteristic.cs" is dragged onto the "characteristics" placeholder within the nucleus script associated with Oxygen.

AND the "NitrogenCharacteristic.cs" script is dragged onto the "characteristics" spot for the nucleus script attached to the nitrogen object.

I hope this makes sense. It's late.

I'm not locked into this solution. If there's another way to accomplish this, please suggest it.

Thanks!

Comment
Add comment · Show 6
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image chariot · Feb 16, 2015 at 08:58 AM 1
Share

Try to create class with your namespace and use it in not genereal scripts. Also, u can get script from another object like this

 public class NucleusScript : $$anonymous$$onoBehaviour {
  
      // External object references
      public GameObject urObj; // attach obj with script here
      public nameOfScript urScr; // placeholder
 
      public void Start (){
           urScr = urObj.GetComponent(nameOfScript); // get component from attached object at start
      }
  
  
      public void reactWithHydrogen(){
           if (distance < urScr.electronegativity){
               // make boom and stuff
           }
  }
avatar image BurningKrome · Feb 16, 2015 at 09:18 AM 0
Share

Hi Chariot, and thanks for the response. I thought of this, but the bug is that I can't create 5 different scripts all named "characteristics.cs" (unity wont allow it).

Which means this is no longer generic, but specific to one molecule...meaning I'm basically doing the same thing as if I re-wrote the NucleusScript 10 times.

Or am I missing something?

See your example updated below to understand what I'm saying...

(for oxygen)

 public class NucleusScript : $$anonymous$$onoBehaviour {
     // External object references
     public OxygenObj GameObject; // attach obj with script here

 // I put the characteristics for Oxygen in "OxygenCharacteristicsScript.cs"
 // Unity will allow only one "OxygenCharacteristicsScript.cs"
     // The cast here for "OxygenCharacteristicsScript.cs" $$anonymous$$UST BE specific to "OxygenCharacteristicsScript", as I understand it
     public OxygenCharacteristicsScript characteristics; 

     public void Start (){
         characteristics = OxygenObj.GetComponent(OxygenCharacteristicsScript); // get component from attached object at start
     }

     public void reactWithHydrogen(){
         if (distance < characteristics.electronegativity){
         // make boom and stuff
         }
     }
 }

So, the above works for Oxygen, but since I have to use a different scriptname (such as "NitrogenCharacteristicsScript.cs") for nitrogen, and I have to change the line...

"public OxygenCharacteristicsScript characteristics;" to "public NitrogenCharacteristicsScript characteristics;"...the NucleusScript is no longer generic and I'll just have to re-write the Nucleus script for every atom. That's what I'm trying to avoid.

Or am I totally missing something?

Thanks!

avatar image Bonfire-Boy · Feb 16, 2015 at 09:29 AM 1
Share

I'm not sure that I understand the question, on the face of it the answer seems to be polymorphism, but that's the case in other languages too. So my simple answer may be missing the point..?

In Unity I'd probably end up with the bare bones looking something like this...

 public abstract class Characteristics <TSpecificCharacteristcs>: $$anonymous$$onobehaviour
 {
      abstract protected float electronegativity (); 
 }
 
 public class OxygenCharacteristics : Characteristics<OxygenCharacteristics> 
 { 
      float ELECTRONEGATIVITY = 3.44; 
  
      public override float electronegativity() { return ELECTRONEGATIVITY; }
  }//class
 
 

And then in the Nucleus class you can have a Characteristics field which could be any of your derived types

 public class NucleusScript : $$anonymous$$onoBehaviour {
  
      // External object references
      public Characteristics characteristics;
  
      public void reactWithHydrogen(){
           if (distance < characteristics.electronegativity){
               // make boom and stuff
           }
  }//end class
 

Having said all that, it's not actually clear to me why you want your Characteristics class to be a $$anonymous$$onoBehaviour, it looks like something that might be better just as a plain old data type. $$anonymous$$aybe a ScriptableObject.

avatar image chariot · Feb 16, 2015 at 09:32 AM 1
Share

U need to create universal script, and in inspector create characteristics (also u can do it in prefab inspector, to instantiates with it).

For example:

  public class UniversalCharacteristic : $$anonymous$$onoBehaviour {
  
      public float ELECTRONEGATIVITY; 
  
      public float electronegativity {
          get {return ELECTRONEGATIVIY;}
          SET {throw new error you can't do this yadda};
      }
 }

Second script:

 public class NucleusScript : $$anonymous$$onoBehaviour {
      // External object references
      public gameObj GameObject; // attach obj with script here

      public UniversalCharacteristicsScript characteristics; 
  
      public void Start (){
          characteristics = OxygenObj.GetComponent(UniversalCharacteristicsScript); // get component from attached object at start
      }
  
      public void reactWithHydrogen(){
          if (distance < characteristics.electronegativity){
          // make boom and stuff
          }
      }
  }

In inspector set for objects:

alt text alt text

sdas.png (6.5 kB)
sdsd.png (6.7 kB)
avatar image BurningKrome · Feb 16, 2015 at 12:44 PM 0
Share

OOOh. I already posted an answer about using inheritance, but I love your UniversalCharacteristics solution. I think I may need to go back and use it ins$$anonymous$$d! Cheers!

Show more comments

3 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by tanoshimi · Feb 16, 2015 at 09:26 AM

"I'm creating a molecular simulation game. It will have lots of atoms with basically all the same functions, but needing different parameters."

From the example code you've given, it seems more like you have atoms with the same properties, but with different values. As such, can you not simply have a single Nucleus script, but set the appropriate ELECTRONEGATIVITY etc. properties via the inspector and save as a prefab for each nucleus type?

Either that, or it sounds like you might want subclasses of nucleus that inherit from the generic base class. e.g.

NucleusScript.cs - use this to define the generic properties that each nuclues will have, but don't actually attach this script to an object.

 using UnityEngine;
 using System.Collections;
 
 public class NucleusScript : MonoBehaviour {
 
     protected float ELECTRONEGATIVITY;
 
     // Define methods that can be overriden with specific implementations in derived classes
     protected virtual void Start () {
     }
     
     protected virtual void Update () {
      }
 }


NitrogenCharacteristics.cs - attach this to a nitrogen atom to override the generic base class methods with specific functionality for the nitrogen class.

 using UnityEngine;
 using System.Collections;
 
 public class NitrogenCharacteristics : NucleusScript {
 
     // Override the Start() method defined in the base class
     protected override void Start () {
         ELECTRONEGATIVITY = 3.04f;
     }
     
 }


OxygenCharacteristics.cs - attach this to an oxygen atom to override the generic base class methods with specific functionality for the oxygen class.

 using UnityEngine;
 using System.Collections;
 
 public class OxygenCharacteristics : NucleusScript {
 
     // Override the Start() method defined in the base class
     protected override void Start () {
         ELECTRONEGATIVITY = 3.44f;
     }
 }



Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image chariot · Feb 16, 2015 at 09:35 AM 0
Share

thats what im talkin about (kind of)

avatar image
1

Answer by Kiwasi · Feb 16, 2015 at 08:34 AM

Are you just asking for an interface? Forgive me if I have any syntax errors

 public interface IHasElectronegativity {
     float electronegativity {get;}
 }
 
 public class NucleusScript : Monobehaviour {
     public IHasElectronegativity characteristics;
 }
 
 public class Oxygen : MonoBehaviour, IHasElectronegativity { 
      public float electronegativity {
          get {return 0;}
      } 
 }

Note that interfaces can't be serialised, but there are tricks to get around this.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Kiwasi · Feb 16, 2015 at 09:22 AM 1
Share

General inheritance may work as well. For example did you consider

 public class OxygenNucleus : GenericNucleus {}
avatar image
0

Answer by BurningKrome · Feb 16, 2015 at 12:44 PM

So, I decided on using good ol' fashioned class inheritance. It's strange to say it felt Klugy (and cumbersome, and difficult) even though some would argue that (programmatically) it's more proper. It just seems like such a builder friendly interface as Unity would have a better (easier) solution.

Maybe they can add this...?

I'm still open to better ways to do this...

---SOLUTION---

(InheritED class, AtomCharacteristics.cs)

 using UnityEngine;
 using System.Collections;
 
 namespace AtomCharacteristics {
     public class Characteristics : MonoBehaviour {
 
         private float ELECTRONEGATIVIY;
         public string testvar = "This is a test variable accessed directly (not through getter).";
 
         // Constructor called when 
         // "Characteristics characteristics = this.gameObject.AddComponent<Characteristics>();" 
         // is used
         public Characteristics() {
             // Set vars and do stuff here if needed
         }// Characteristics constructor
 
         // Must be initialized since MonoBehaviour doesn't allow passing variables to constructors
         public void Init(string atomType) {
             if (atomType.IndexOf("Oxygen") > -1)  {ELECTRONEGATIVIY = 3.44F;} // should prolly use another class constructor to set all this
             if (atomType.IndexOf("Nitrogen") > -1){ELECTRONEGATIVIY = 3.04F;} // should prolly use another class constructor to set all this

         }// Init
 
         // Getter/Setter for electronegativity
         public float electronegativity {
             get { return ELECTRONEGATIVIY; }
             set { ELECTRONEGATIVIY = value; }
         }//electronegativity
 
     }//class Characteristics
 }// namespace AtomCharacteristics
 

(InheritING class, NucleusScript.cs)

 using UnityEngine;
 using System.Collections;
 using AtomCharacteristics; // My constructor class
 
 
 public class NucleusScript : Characteristics {
 
     void Start() {// Use this for initialization ------------------------------------------
         Characteristics characteristics = this.gameObject.AddComponent<Characteristics>();
         characteristics.Init("Oxygen");

         Debug.Log("(testCharacteristics)Electronegativity is " + characteristics.electronegativity);
         Debug.Log("(testCharacteristics)testvar is " + characteristics.testvar);
     }//Start 
 
     void Update() {    // Update is called once per frame 
     }//Update
 
     public void reactWithHydrogen(){
          if (distance < characteristics.electronegativity){
          // make boom and stuff
     }//    reactWithHydrogen

     ////// other fun and useful method //////
 }//end class




Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bonfire-Boy · Feb 16, 2015 at 01:39 PM 0
Share

That doesn't look at all right. Why is AtomCharacteristics a $$anonymous$$onoBehaviour when it uses no features of $$anonymous$$onoBehaviour (and does have a constructor)??

avatar image BurningKrome · Feb 16, 2015 at 04:27 PM 0
Share

Well...part of the issue is Im new to C# (mostly I work in Python).

$$anonymous$$y assumption is that, since the child script which inherits from Atomcharachteristics will also contain methods to run objects, that I would need $$anonymous$$onoBehavior somwhere in the inheritence chain.

It does indeed FUNCTION in the expected manner...?

avatar image BurningKrome · Feb 16, 2015 at 04:30 PM 0
Share

hariot also made the suggestion to use a Universal script with variables in the inspector...which I think is a better answer.

avatar image Bonfire-Boy · Feb 16, 2015 at 04:50 PM 0
Share

I really think you'll be glad later on if you take your time over this design, or it'll come back to bite you.

Seems to me that these are OO design issues as much as specifically C#/Unity ones. Generally speaking, one doesn't want to put the specialisation in the base class. So if you want to use inheritance in your main classes it would make more sense to do it the other way round, with Nucleus as your base class (derived from $$anonymous$$onoBehaviour) and then subclasses for each of the elements which add specialisation. This would model the real world better.

For example, in the real world, an atom's nucleus can change. By making the characteristics of a nucleus object deter$$anonymous$$ed by its base class, you'll make things like that difficult if you want to do them later on. I'd want the characteristics to be a property (field) of a nucleus... much more like what you were doing to start with (but with the various elements' characteristics subclasses of a simple, non-$$anonymous$$onoBehaviour Characteristics class, or maybe a ScriptableObject).

avatar image BurningKrome · Feb 16, 2015 at 05:28 PM 0
Share

I agree with you about the Nucleus being the base class...which was my original intent. This is my Unity "learning" project and things got a bit turned around while experimenting. $$anonymous$$y original plan was just to have one script - Nucleus - with configuration files. But that didn't work out. And 2A$$anonymous$$.

Although, In what I've read about Unity I got the impression that everything had to - in one form or another - inherit from $$anonymous$$onoBehavior...otherwise things break...?

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

How to use variable in MailMessage To? 1 Answer

Variable set twice on the same Update call - Second time doesn't update? 2 Answers

Accessing tiles in another class 0 Answers

Access object script from prefab script 1 Answer

Accessing variables from GameObjects in an array 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges