I have a script for an animation that requires the variable “_ball”, which is in a separate script, to increment past 0.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PinWiperAnimation : MonoBehaviour
{
Animator myAnimator;
public BallReturn ballReturn;
void Awake()
{
ballReturn = GetComponent<BallReturn>();
myAnimator = GetComponent<Animator>();
}
const string PinWiper = "StartPinWiper";
// Start is called before the first frame up
void Start()
{
myAnimator = GetComponent<Animator>();
}
void Update()
{
if (ballReturn._ball != 0)
{
myAnimator.SetTrigger(PinWiper);
}
}
}
The issue is that while the _ball variable does indeed get to one then two, the PinWiperAnimation script never sees the updated value, just what it is initialized as which is 0. If i change the condition to ballReturn._ball != 1, the animation does indeed start. So its just how im passing it. Here is the script im pulling _ball from:
using UnityEngine;
using System.Collections;
public class BallReturn : MonoBehaviour
{
public int _ball = 0;
bool doUpdate = false;
public PinWiperAnimation pinWiperAnimation;
void Awake()
{
pinWiperAnimation = GetComponent<PinWiperAnimation>();
}
void FixedUpdate()
{
if (doUpdate)
{
_ball += 1;
_ball = _ball % 3;
StartCoroutine(DelayUpdate());
// pinWiperAnimation.AnimationStatus();
}
doUpdate = false;
}
public IEnumerator DelayUpdate()
{
yield return new WaitForSeconds(1.5f);
gameObject.SendMessage("UpdateScore", _ball, SendMessageOptions.RequireReceiver);
yield return 0;
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.GetComponent<FixBallSpeed>() != null)
{
doUpdate = true;
other.gameObject.SendMessage("Reset", _ball, SendMessageOptions.DontRequireReceiver);
// pinWiperAnimation.AnimationStatus();
}
}
void ResetFrame()
{
foreach (var v in GameObject.FindGameObjectsWithTag("pin"))
{
v.SendMessage("ResetPin", (_ball), SendMessageOptions.DontRequireReceiver);
}
_ball = 0;
}
}
Referencing variables, fields, methods (anything non-static) in other script instances:
REMEMBER: it isn’t always the best idea for everything to access everything else all over the place. For instance, it is BAD for the player to reach into an enemy and reduce his health.
Instead there should be a function you call on the enemy to reduce his health. All the same rules apply for the above steps: the function must be public AND you need a reference to the class instance.
That way the enemy (and only the enemy) has code to reduce his health and simultaneously do anything else, such as kill him or make him reel from the impact, and all that code is centralized in one place.
Also as a convention we don’t do _underscore thing with public variables.
The idea is that you want to achieve two things with such naming conventions: 1) easily tell whether a function has side-effects (i.e. whether it cross-references external variables), 2) easily tell whether a variable is local to the internal logic or not.
So we introduce the underscore on private class fields to achieve both. If you keep your arguments underscore-free, you can easily tell if a function is “pure” or not, and believe me after decades you begin to structure your code in a manner that can filter these subconsciously, so it must be worth something. Likewise, your more “internal” methods, responsible for critical state recognition and switching behavior, onto which you hook your public API more as a facade, will usually rely on underscored class fields much more readily, and this way you can easily introduce public getters and setters with the same name, as an example, but also quite easily tell and prevent errors (or underperformance) that might arise from wrongly accessing such getters and setters instead of their backing fields and other local information in a direct manner.
Here’s a useful mnemonic: the underscore is there to remind you of “ugly”. Ugly means “for your eyes only”. You don’t want to present an ugly face of your encapsulation to the public domain of your system at large. This is just the core OOP “mechanic”.
Of course you’re free to have your own personal style, but this little thing goes pretty much against every fiber in the programming community. Sorry about the tangent, I just thought it was worth explaining.
So reading both those forums im not sure how they apply to my issue, maybe im missing something. Are you suggesting I should not use the GetComponent to inherent the class like the first forum is trying to do?
I would LOVE to keep the animation controller in one place, like inside the BallReturn scripts ive shown above. Here is the issue with that. Not sure if you saw but in that script o am using a collider to triggers a gameobject respawn when the ball hits the floor. So this script must be attached to the floor. Problem is when i add the animator to the BallReturn script, any object that has that script attached to it complains that an animator is trying to call it but none are attached. Im not sure how that can be decoupled outside of using a separate script
If both objects are in the scene you should assign the references in the inspector instead of using GetComponent in the code. GetComponent is not needed when you assign references through the inspector. It’s mostly useful if you don’t design your objects in the scene or as a prefab.
Or if reacting to a dynamic event like OnTriggerEnter, like you do in your code already. This in mind, if you use GetComponent like that there is no reason to use SendMessage to run a method on that object, you can just call it directly using the reference you get from GetComponent.