#Posting code
1 messages · Page 1 of 1 (latest)
the link
once you paste there should be some save or share button on most sites
private bool SpawnBall()
{
Instance = Instantiate(ballPrefab, m_launchEndPoint.position, Quaternion.identity);
Instance.GetComponent<Rigidbody>().useGravity = false;
Debug.Log($"SpawnBall: Instance: {Instance.name}");
return true;
}
this is what's called when you launch the ball. it doesn't use the ball you already created, just spawns a new one. you'll want to sub to its destroyed event, since it's a new object
The logic for validating that there is no instanced ball in the air is handled in OnPress() (although I really should probably just put it in SpawnBall()
(post the paste site link already, its really annoying reading the original code in discord)
they editted their original post
ah ok
So why does it invoke destroyed correctly the first time a ball is instanced at runtime?
I would also not use unity event for this, it can just be a standard c# event since you're gonna need to subscribe at runtime anyways. but still you dont truly need events here unless. you're kinda doing both things where you use an event to know when the object is destroyed, AND checking the Instance anyways
I have it set up such that the prefab for the ball is connected to the prefab for the projectile instance handler
I really also should rename the Instance variable. That refers to the instance of ball that is currently being babysat by the projectile handler (not any ball that is in the air)
that's why instance is set to null in OnRelease
this code sucks major lol i'm sorry
not exactly sure how you have it set up, the prefab reference is likely updating to the spawned instance which is how it works normally if you for example reference another component in your same prefab
lemme screenie
oh i see the first ball is used. it's like pre-loaded into the launcher or something. so a new one isn't spawned
im aware, look at your code though. IsBallInAir is basically the same information to you as Instance.
these are all done at the same time
Instance = null;
IsBallInAir = false;
...
IsBallInAir = true;
Instance = null;
...
if (Instance == null)
{
Debug.LogError("OnPosition: Instance is null.");
return;
}
if (IsBallInAir == true)
{
Debug.LogError("OnPosition: Ball already in flight.");
return;
}
either way the fix is to sub to the destroyed event in SpawnBall()
If you mean that the first instance is not instantiated at runtime, incorrect. It is
either way the fix is to sub to the destroyed event in SpawnBall() lol
The first one is for OnBallDestroyed(), which means:
- There's no ball in the launcher
- There's no ball on the map
The second one is forLaunchBall(), which means: - There's no ball in the launcher
- There IS a ball on the map
So you're saying that the OnBallDestroyed() method isn't listening to the first ball instance that is spawned, even though I get the debug logs for it?
Im saying you should add this line to SpawnBall:
private bool SpawnBall()
{
Instance = Instantiate(ballPrefab, m_launchEndPoint.position, Quaternion.identity);
Instance.destroyed.AddListener(OnBallDestroyed); <- add line
Instance.GetComponent<Rigidbody>().useGravity = false;
Debug.Log($"SpawnBall: Instance: {Instance.name}");
return true;
}
Oki, then I'll do that and remove the listener from the prefab (just in case it gets sent twice or something)
i'm really bad at using events lol
i'm kinda bad at coding, as this code demonstrates
idk what you're doing with the first one that makes it work so I think im missing information, but really it doesn't matter since it's working. the problem is the other balls after that, which subbing in SpawnBall would fix.
I'll attempt that and come back if need be
I think I'm gonna probably just redesign the whole system cause it sucks lol
no worries i spent 4 years coding before i learned arrays were a thing. I had so much code doing int1, int2, int3, int4 ...
your entire ball code could literally be
public class Ball : MonoBehaviour
{
public UnityEvent<Ball> destroyed = new UnityEvent<Ball>();
void OnCollisionEnter(Collision other)
{
Destroy(gameObject);
}
void Update()
{
if (transform.position.y < -2)
{
Destroy(gameObject);
}
}
void OnDestroy()
{
Debug.Log("Ball instance destroyed!");
destroyed?.Invoke(this);
}
}
although i would probably move the addForce method to there so the ProjectileInstanceHandler has less to do
Oki, so the reason I'm implementing my own interface for this is so I can have the game manager capture events from when enemies get hit and now that I say it out loud, it's kinda unnecessary yeah lol
yeah, that's the other reason I wanna completely overhaul the Projectile Instance Handler. It currently doesn't do it's singular responsibility rn
it's handling inputs, the ball, the gamestate. It's basically a glorified game manager lmao
when you instantiate an object, you can reference it by the component you want to actually spawn.
public Ball ballPrefab;
public Ball currentBall;
private bool SpawnBall()
{
currentBall = Instantiate(ballPrefab, m_launchEndPoint.position, Quaternion.identity);
currentBall.Setup(); // <- ball has a ref to its own rigidbody and sets gravity to false
}
private void LaunchBall()
{
currentBall.Launch(m_direction * m_distance * FORCE_MULTIPLIER, ForceMode.VelocityChange);
// ..then set current ball to false if you want
}
if you can simplify your own code it will be a lot easier for you to see whats wrong
i mean given how simple this is, i dont think its a big deal. for a game like this id just keep it as is
that's a much better idea lol thank you!
unless you have parts where you actually need to control what is given input, its fine to just let this class subscribe to input