Variable Updating after Runtime

Hello,

I’m currently trying to make a gun script make an enemy take damage (as shown below). The method is called as the debug.Log is called, and the variable changes. However, this change is applied after runtime and the health variable remains at 100.

9473323--1331590--Capture.PNG
9473323--1331593--Capture2.PNG

Sounds like you wrote a bug!! That can only mean…

Time to start debugging!

By debugging you can find out exactly what your program is doing so you can fix it.

Here is how you can begin your exciting new debugging adventures:

You must find a way to get the information you need in order to reason about what the problem is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the names of the GameObjects or Components involved?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as Debug.Log("Problem!",this);

If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer for iOS: https://discussions.unity.com/t/700551 or this answer for Android: https://discussions.unity.com/t/699654

If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

If your problem is with OnCollision-type functions, print the name of what is passed in!

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

https://discussions.unity.com/t/839300/3

If you are looking for how to attach an actual debugger to Unity: https://docs.unity3d.com/2021.1/Documentation/Manual/ManagedCodeDebugging.html

“When in doubt, print it out!™” - Kurt Dekker (and many others)

Note: the print() function is an alias for Debug.Log() provided by the MonoBehaviour class.

Once you learn more…

How to report your problem productively in the Unity3D forums:

http://plbm.com/?p=220

This is the bare minimum of information to report:

  • what you want
  • what you tried
  • what you expected to happen
  • what actually happened, log output, variable values, and especially any errors you see
  • links to documentation you used to cross-check your work (CRITICAL!!!)

The purpose of YOU providing links is to make our job easier, while simultaneously showing us that you actually put effort into the process. If you haven’t put effort into finding the documentation, why should we bother putting effort into replying?

If you post a code snippet, ALWAYS USE CODE TAGS:

How to use code tags: https://discussions.unity.com/t/481379

  • Do not TALK about code without posting it.
  • Do NOT post unformatted code.
  • Do NOT retype code. Use copy/paste properly using code tags.
    - Do NOT post screenshots of code.
    - Do NOT post photographs of code.
  • Do NOT attach entire scripts to your post.
  • ONLY post the relevant code, and then refer to it in your discussion.

Thank you for helping me learn more about this! I was unaware of any debug options outside of Debug.Log() and Debug.DrawRay(). I’ve updated it below.

I want the enemy GameObject health variable to reduce by the gun script’s damage variable on a raycast hit and have it be deleted after reaching a value of 0. The enemy health is set to 100 in the inspector, and the damage is set to 50. I’ve tried using a bool check in the enemy script’s update method, and subtracting the enemy health variable in the gun script, neither of which have worked. My current attempt is referencing a method in the enemy script in the gun script.

void Shoot()
    {
        flash.Play();
        readyToFire = false;
        StartCoroutine(FireRate());
      
        RaycastHit hit;
      
        if (Physics.Raycast(cam.position, cam.forward, out hit, 500f, whatIsEnemy))
        {
            enemyScript.Damage(damage);
        }
    }
void Update()
    {
      
        if(health <= 0)
        {
            Destroy(gameObject);
        }
    }


    public void Damage(float dam)
    {
        Debug.Log("hit");
        health -= dam;
        Debug.Log(health);
    }

However, what instead happens is the above method is called and ran, but the health variable remains at 100 in the inspector until exiting runtime. The health does log as going down as expected, but the value does not change in the inspector, and as a result the object is never destroyed.

“enemyScript” is a vague name.

Is this a prefab?

Or is it the one you instantiate-d in scene?

It matters.

It’s always best to name things as prefabs or instances:

public GameObject enemyPrefab;  // <-- the one on disk
public GameObject enemyInstance;     // <-- the actual running one

My guess is you are decrementing the enemy prefab on disk.

enemyScript is the variable that holds the script attached to the enemy. You are correct in your guess, it is decrementing in the prefab asset rather than the object in the scene, so I need to change that. Thank you for your help! I’ll update the post once I get home and I’m able to verify that the issue is resolved.

1 Like

Excellent. The usual technique is to go digging for the enemyScript by looking at what you hit, eg, fields in the RaycastHit struct.

Caution: make sure you actually FIND an enemy script before you go damaging it, otherwise NullReferenceException, obviously. :slight_smile:

Setting the enemy to an actual instance of the enemy was what fixed it, thank you! I made this script very late last week and not only have I learned a lot just in experience making this game, I’ve also slept like a normal human!! (cue applause)

Thanks for your help, I really appreciate it. Kind of a dumb mistake I made, but we all make those when we’re starting out.

Do you only have a single enemy in your game? If that is the case, your code would work. However if you have more than one or dynamically create more enemies, you should use the “hit” variable of your raycast and get the enemy script from the actual object that your ray hits. Currently it doesn’t matter what you actually hit. As soon as your raycast hits anything that matches the layer mask you will apply damage to that on enemy that you manually referenced.

This I figured out on my own, I just had the manual reference as a placeholder to get the mechanic worked out.

It’s a great journey. I’ve been using Unity for over a decade and I actually STILL picked up a few new tidbits from this video that dropped a few days ago… it’s my new favorite video for the simple basics of how code works in Unity3D: