Jump to content

Unity/ C# sharp simplest problem ever

HeartOfGermany

 

Hello folks. I feel kinda stupid for asking. It actually is the simplest thing in the world, but I do not understand some basic logics this time. I watched a Video on YouTube called "How to Start Making Games - Unity Playground (Beginner Friendly)". And I tried to make a demo project like asteriods with "Unity Playgrounds". I got my ship shooting lasers and the asteroid gets destroid, once hit. The problem is, I want to add health, so you need to hit it 3 times. I need a variable like gameObject.health. From my CoD4 scripting experience it was like this: self.health = 0; predefined the child variale health to self which is the gameobject player. Why can I not do this with C sharp (C#), when using private/publich int gameObject.healtPoints = 15;? This does not work, but why? Because destroy gameObject; infact destroys the asteriod. So the parent "gameObject" seems to be correct as parent of the variable gameObject.health. How do I define this variable, to later be used ingame? What am I missing? Please do not tried to explain the basic C# rules - this problem is not just about C#. I need an example, to understand the rules behind that. So what did I do wrong in this case?


It is important to me, I actually got quite some plans. But this basic barrier actually stops me from doing anything really useful. I would not have asked here, if answers.unity.com was of any help. zero answers after over a week! Nothing. I am frustrated that even the main page does not help. And videos are often also not helpful. They only show you how to copy code, but do not explain, what the code actually does. I am absolutely stuck here trying to understand this variable/object problem. Thought, this will be really simple, since I  actually scriped a lot with CoD4 and was actually quite very good at the end.

 

 

This is the problem code. All I have added is stuff named "..... healthPoints.....". Anything else was there before and was working perfectly.

 

 [AddComponentMenu("Playground/Attributes/Destroy For Points")]
 public class DestroyForPointsAttribute : MonoBehaviour
 {
     public int pointsWorth = 5;
     private UIScript userInterface;
   private int this.gameObject.healthPoints = 15;
     private void Start()
     {
         // Find the UI in the scene and store a reference for later use
         userInterface = GameObject.FindObjectOfType<UIScript>();
     }
     
 
     //This will create a dialog window asking for which dialog to add
     private void Reset()
     {
         Utils.Collider2DDialogWindow(this.gameObject, false);
     }
     
     //duplication of the following function to accomodate both trigger and non-trigger Colliders
     private void OnCollisionEnter2D(Collision2D collisionData)
     {
         OnTriggerEnter2D(collisionData.collider);
     }
 
     // This function gets called everytime this object collides with another trigger
     private void OnTriggerEnter2D(Collider2D collisionData)
     {
         // is the other object a Bullet?
         if(collisionData.gameObject.CompareTag("Bullet"))
         {
 
        if(this.gameObject.healthPoints == null)
        {
         this.gameObject.healthPoints = 15;
        }
        this.gameObject.healthPoints -= 5;
        if (this.gameObject.healthPoints < 1)
        {
              if(userInterface != null)
              {
                   // add one point
                   BulletAttribute b = collisionData.gameObject.GetComponent<BulletAttribute>();
                   if(b != null)
                   {
                      userInterface.AddPoints(b.playerId, pointsWorth);
                   }
                   else
                   {
                      Debug.Log("Use a BulletAttribute on one of the objects involved in the collision if you want one of the players to receive points for destroying the target.");
                   }
              }
              else
              {
                   Debug.Log("There is no UI in the scene, hence points can't be displayed.");
              }
 
              // then destroy this object
              Destroy(gameObject); // Oh hello guys!!!! This is what I mean. It destroys the asteriod. So shouldnt int gameObject.health just be working? But it is, like gameObject is just locked down to what already is there.
              // Also I do not understand, how to add a script and get a prompt in the user interface for the prefab,
              // to predefine the health of an asteroid. Like:
              // int gameObject.health = createConfig("Asteroid health", "This variable (int) will set the health of the asteroid.", int 1);
              // -> explained: createConfig("Variable name for interface", "Help text that shows to explain the input", int default_value_if_undefined);
              // I am asking, because I keep seeing this, but never know, where those custom inputs in the user interface from scripts actually come from!
              // For example there is a script for projectile firing, that I usue for my laser. It asks for the speed for example in the UI on the right side of the screen. How?
           }
      }
     }
 }

 

 

So what is wrong here?

 

 

At last: A facepalm on me for not getting this, thanking you for the answer!

Link to comment
Share on other sites

Link to post
Share on other sites

You should format your code better.

 

As for the question, the GameObject class does not have a "health" property. https://docs.unity3d.com/ScriptReference/GameObject.html

 

If you want to represent health like that you'll have to extend the base class. Or maybe there's another way, I'm not quite familiar with how Unity works - regardless trying to access properties that aren't defined won't work.

Don't ask to ask, just ask... please 🤨

sudo chmod -R 000 /*

Link to comment
Share on other sites

Link to post
Share on other sites

2 hours ago, HeartOfGermany said:

private int this.gameObject.healthPoints = 15;

 

Why did you add 'healthPoints' to the gameObject, rather than simply making it a variable in this script (or better yet, a script/class specifically for health management)?

There are a lot of ways to go about doing this, from the extremely simple ways to to more elaborate ways. Which you should choose depends on what you are going to do with this game.

 

 

Simple way:

public class PlayerHealthManager : MonoBehaviour {

    private int playerHealth;

    void Start()
    {
        playerHealth = 3;
    }

    public void HurtPlayer(int damageAmount)
    {
        currentHealth -= damageAmount;
        if(currentHealth <= 0)
        {
            // player dead
        }
    }

    public void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.tag == "Enemy")
        {
            int damage = 1;
            HurtPlayer(damage);
        }
    }
}

 

Basically you make a global variable at the top of your script (because Unity doesn't do properties for some reason, if memory serves me right), initialize this variable in Start(), you have an OnTrigger function, check if what you collide with is tagged as an enemy (or maybe tagged as hurtable object? Like spikes would be too for example?), then you remove some health.

In your HurtPlayer() function you also check if the player has died and do what you must accordingly (usually call another script to take you to a 'game over' scene and save score.. etc. etc.)

 

Reason I mention this is the simplest way is because it leaves room for expandability. Maybe you want some 'elemental' bullets? Bullets with different damage? Want a shield for different things? With the OnTrigger function you're seeing the collider the 'enemy' is and can extrapolate detail from it (from its tag and name) to decide if your player is for example weak to this or not.

But it doesn't quite store things like the names of the enemy, their score, etc. etc. Only the collider.

 

P.S. If you are using Visual Studio (which I think is the default editor nowadays?) formatting your script is super easy. Just do this:

1. Ctrl+A (to select all in the script)

2. Ctrl+K

3. Ctrl+F

 

And now it's beautifully formatted :) 

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to comment
Share on other sites

Link to post
Share on other sites

So far so good. This helps actually. It is pointing me in the right direction.

 

Now I also understand something.

 

private int something_integer_alike;

 

This variable is only for THIS gameobject, right? If not, this variable could only be used once, because it would be a public integer, right? So is it possible, to be called outside of the script?

 

That is the reason, why I thought of something like objectname.variablename in the first place.

 

I mean, what, if I have 1000 asteroids. How do I call the health value of the asteroid 534?

 

 

 

 

 

Actually I am not using visual studio. I used PSPad. It formats it different. I actually used notepad.exe for all of my CoD4 scripting. :D It worked perfectly. The formatting part however makes it interesting to usue visual studio. It autoformats something like:

 

if (...whatever) {

something;

}

 

to

if (...whatever)

{

 something;

}

 

? If so, I realy love it. I hate seeing if(...) {

 

This bracket belongs on the next line! :D

 

Sorry for the formatting anyway. Will not continue to use PSPad for anything complex, since the formatting is not my flavour.

 

 

 

 

Thaaaaaaanks a loooot, guys!

 

 

❤️

Link to comment
Share on other sites

Link to post
Share on other sites

6 minutes ago, HeartOfGermany said:

This variable is only for THIS gameobject, right? If not, this variable could only be used once, because it would be a public integer, right? So is it possible, to be called outside of the script?

The variable is part of a script, the script is part of the gameObject. 

So if I make 100 instances of one/different gameObject that all use this script, that means all 100 gameObject will have their own instance of this script, which all will have their own respective instance of this variable.

So editing 'health' on Asteroid#001, will not impact the 'health' on Asteroid#002 and so on.

 

The Health variable is public though, so doing something like 'Asteroid#001.ScriptName.Health' means you will be able to access it. That is not the right syntax to access the variable, it's more to show where the variable is stored.

 

You can access this variable from outside the script. But should you? That is a much more complicated question and goes into the thought behind 'Object oriented programming' (henceforth; OOP), touches on certain 'Design patterns', etc.

I would kinda briefly explain OOP.

 

The idea is that every object (instance of a gameobject, instance of a script, instance of a variable, etc.) is responsible for itself.

So you can't have player change the health of the enemy. But you can have player inform the enemy that they received damage, so the enemy can change their health themselves.

In that way. Do you want player to say "hey asteroid, your health = 0 now" or should you have player inform the asteroid its health should be 0 now?

The former is easier. The latter is better when thinking about future expand-ability, but also ease of reading your code.

When I want to change the behavior of the enemy, I only need to look at enemy code. Not dig around everywhere, where the enemy might just be mentioned.

 

So no, you don't change the health of an enemy inside the player script. You can however call a public method belonging to the enemy, from inside the player script.

Or better yet, have the enemy figure out all their health stuff on their own!

16 minutes ago, HeartOfGermany said:

That is the reason, why I thought of something like objectname.variablename in the first place.

I mean, what, if I have 1000 asteroids. How do I call the health value of the asteroid 534?

If you have the gameObject, you can theoretically do it like this:

// Call a variable of another object
object.gameObject.GetComponent<ScriptNameGoesHere>().VariableNameGoesHere;

// Call a method of another object
object.gameObject.GetComponent<ScriptNameGoesHere>().SomeVeryNiceMethodHere(ParameterHere);

// Example of how this can be used in Unity:
// (method I actually used in a simple 'space shooter' game)
// (This method was used on a bullet, so it Destroys itself at the end)
private void OnCollisionEnter(Collision other)
{
	if (other.gameObject.tag == "Enemy")
	{
		other.gameObject.GetComponent<EnemyHealthManager>().HurtEnemy(damageToGive);
		Destroy(gameObject);
	}
}

I would only recommend if you're doing this sort of stuff if you're going to create an UML for the game, so you know what Scripts will be calling other scripts.

 

But again, think long and hard if you should actually access the health of Asteroid#534. Why wouldn't you have Asteroid#534 deal with its health itself? Have the asteroid check if it got hit, if it has got health left.. Etc.

Then you only need to make a single prefab with script, which you can instantiate whenever, which will deal with all the stuff itself.

 

28 minutes ago, HeartOfGermany said:

? If so, I realy love it. I hate seeing if(...) {

In Visual Studio, when I write:
 

if(1==1){

it will automatically add the second curly bracket like this:

if(1==1){ | }

The line/pipe inbetween the curly brackets representing my cursor, because when I now press Enter, it will format the If statement like this:

if(1==1)
{
	|
}

(Again, the line/pipe representing the cursor).

So yes, it formats if-statement in the (IMO) right way!

 

It also does this for other pieces of code that use the characters (like methods, else, etc.).

Visual Studio will also try to help you during programming, by giving hints/suggestions on what to variables and function to use.

Plus, if you out a summary above your functions (by pressing the forward slash (/) three times above a function), you can even quickly see what a function does:

image.png.0225720387ad897c16fcafdd95d967de.png

 

Sorry for the long post, just had quite a few things to say.

 

P.S. if your respond to other users on this website, it's best to 'quote' them using this button:

image.png.197794b998470e000a49a504f37623bc.png

That way I (and others) will be notified of your reply.

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, minibois said:

What you said - this will notify you, right?

 

Thank you a lot. The answer is perfect now! I gues, now I almost fully understand C# basics. That was very helpful, so realy thank you for your time.

Link to comment
Share on other sites

Link to post
Share on other sites

30 minutes ago, HeartOfGermany said:

Thank you a lot. The answer is perfect now! I gues, now I almost fully understand C# basics. That was very helpful, so realy thank you for your time.

Yep, using that button (the quote button) I am notified of your reply :)

Keep in mind I barely scratched the surface of OOP (which can apply to really any programming languages that has objects), but great to hear I was able to help you out!

 

Have fun coding!

"We're all in this together, might as well be friends" Tom, Toonami.

 

mini eLiXiVy: my open source 65% mechanical PCB, a build log, PCB anatomy and discussing open source licenses: https://linustechtips.com/topic/1366493-elixivy-a-65-mechanical-keyboard-build-log-pcb-anatomy-and-how-i-open-sourced-this-project/

 

mini_cardboard: a 4% keyboard build log and how keyboards workhttps://linustechtips.com/topic/1328547-mini_cardboard-a-4-keyboard-build-log-and-how-keyboards-work/

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×