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
0
Question by PsychoPsam · Mar 25, 2013 at 03:40 PM · staticcollisionsnon-staticaccessor

Assessing variables from other scripts using an accessor seems inelegant. Please explain.

As near as I can tell based on this reference... Referencing non static variables from another script? C# ... the following code below is how I have to access variables ( members public or private ) from one script via another script.

Notice that I make another class inside my EnemyControl script to access the health from EnemyControl, even though health is public. Also I have to set my accessor method "updateHealth" to static to resolve a compiler error (An object reference is required to access non-static member).

My question is, is this the correct way to do this? It seems a little cludgy/hacky.

Here's my calling code...

     // detect collisions
      void OnCollisionEnter(Collision collision) 
     {
         if (collision.gameObject.name == "Enemy")
         {
             // add to score
             HudManager.addToScore(10);
             
             // modify enemy health
             Accessor enemyScript = collision.gameObject.GetComponent<Accessor>();
             Accessor.updateHealth(-1, collision.gameObject);
             
             // kill off bullet
             Destroy (this.gameObject);
             
         }
     }



Here's the accessor code.

 using UnityEngine;
 using System.Collections;
 
 public class EnemyControl : MonoBehaviour {
     
     public int health = 100;
 
     // Use this for initialization
     void Start () {
     
     }
     
     // Update is called once per frame
     void Update () {
         
     }
     
     
     
 }
 
 public class Accessor : MonoBehaviour {
     
     // update health
     public static void updateHealth( int val, GameObject which )
     {
         which.GetComponent<EnemyControl>().health -= val;
         Debug.Log ("Enemy takes a hit");
     }
 }

As an aside, HudManager.addToScore() was done using static members and declaring the method static as well. I was okay with this because HudManager is a singleton but I need EnemyControl to work on instances of the enemies as they spawn. Here's the HudManager code anyway... ( for the sake of search engines this code shows how to fire projectiles at the enemy and detect collisions with the enemy ) I'm also using NGUI for the HUDs.

 using UnityEngine;
 using System.Collections;
 
 public class HudManager : MonoBehaviour {
     
     public static int ammo = 256;
     public float bulletSpeed = 11;
     public static int score = 1;
     public GameObject projectile;
     
     private static UIBaseLabel ammoText;
     private static UIBaseLabel scoreText;
     
     
     
     // Use this for initialization
     void Start () {
         
         // initial update UI
         ammoText = GameObject.Find ("AmmoLabel").GetComponent<UIBaseLabel>();
         ammoText.text = "Ammo:" + ammo;
         
         // initial update UI
         scoreText = GameObject.Find ("ScoreLabel").GetComponent<UIBaseLabel>();
         scoreText.text = "Score:" + score;
     }
     
     // Update is called once per frame
     void Update () {
         
         // check for firing
         if (Input.GetMouseButtonDown(0))
         {
             // reduce ammo counter
             if ( ammo > 0)
             {
                 ammo -= 1;
             
                 // update ammo counter
                 ammoText.text = "Ammo:" + ammo;
                 
                 // Instantiate the projectile at the position and rotation of this transform
                 GameObject gunNozzle = GameObject.Find("Nozzle");
                 GameObject clone = Instantiate(projectile, gunNozzle.transform.position, gunNozzle.transform.rotation) as GameObject;
                 
                 // Add force to the cloned object in the object's forward direction
                 clone.gameObject.AddComponent<Rigidbody>();
                 clone.rigidbody.mass = 0.1f;
                 clone.rigidbody.useGravity = false;
                 clone.rigidbody.AddForce(clone.transform.forward * bulletSpeed);
                 
                 // attach script
                 clone.gameObject.AddComponent("projectileController");
             }
         }
     
     }
     public static void addToScore(int val)
     {
         // increment score by amount
         score += val;
         
         // update UI
         scoreText.text = "Score:" + score;
     }
 }

Comment
Add comment
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

3 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by robertbu · Mar 25, 2013 at 04:09 PM

Why the "Accessor" class? Why not just put UpdateHealth() inside your EnemyControl class? UpdateHealth would not be static inside of the EnemyControlClass, and it would be tied to the instance of the class (and therefore the game object). Then you could do something like:

 EnemyControl enemyScript = collision.gameObject.GetComponent<EnemyControl>();
 if (enemyScript != null)
     enemyScript.updateHealth(-1);
Comment
Add comment · 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
0

Answer by PsychoPsam · Mar 26, 2013 at 01:01 AM

Thanks for you help. Aww - man, now I understand. When I did this yesterday as you explained it gave me the error "An object reference is required to access non-static member".

It was because I called it explicitly... EnemyControl.updateHealth(-1); ... which is not allowed (not sure why).

So theoretically the HudManager should work the same. Now I get it :D

This the object reference that is needed to access a non-static member...

HudManager hudScript = GameObject.Find("Player").GetComponent(); because HudManager is sitting on Player.

So then I can call... hudScript.addToScore(10);

All sorted and now I understand - except, why do they have to be referenced and not be able to be called explicitly?

Comment
Add comment · 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
0

Answer by PsychoPsam · Mar 26, 2013 at 01:03 AM

Actually I think I understand now. All scripts tend to be put on an instance of an object, so you need to reference the component attached to that object to get the actual instance of the script. The only way for something to be accessed directly, ie HudManager.addToScore is to make it singleton and make all the method static.

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 robertbu · Mar 26, 2013 at 02:29 AM 0
Share

A singleton and static variables are not the same thing. I'm out of town with only an iPad, so it is difficult for me to look up some reference for you. Google "Unity3d singleton" and you will find a number of hits to direct you. Also you can have both class methods and instance methods in a class. Take a look at the reference page for Quaternion for example of a class with both. As long as a method does not access instance data, it can be static and called by using the class rather than an instance reference.

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

10 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

C# Going Static or Going OOP 3 Answers

How to use non static field in static member? 1 Answer

Script Errors with Unity 3.0 0 Answers

How to attach a script to a static Tree Prefab? 1 Answer

Unable to modify a variable in another script 2 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