Health Regeneration through Photon RPC
Hi guys, i'm trying to add Health Regen through Photon PunRPC. It's working but i'm having issues with the logic, at this point, it runs only once because i'm validating to avoid getting in there so many times in the Update() and it will eventually bug. But how can I achieve this? I'm trying to make the Health Regen to start after 8 seconds of not getting hit by another player and then, add 15 health every 4 seconds until it's maxed out.
Here's my current code:
Each lastTimeHit
is set whenever any of the players gets hit. Its value is another DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
public Player player;
private long playerLastTimeHit = 0;
private long otherLastTimeHit = 0;
private bool isCoroutineExecuting = false;
[SerializeField]
float TIME_UNTIL_REGEN = 8f;
public void Update()
{
checkHealthRegen();
}
[PunRPC]
public void reduceHealthWithAR() {
reduceHealthAmount(0.4f);
}
private void checkHealthRegen() {
long lastTimeHit = (photonView.isMine) ? playerLastTimeHit : otherLastTimeHit;
long currentTimeMillis = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
float deltaTime = (float)((currentTimeMillis - lastTimeHit) / 1000);
if (Mathf.Approximately(TIME_UNTIL_REGEN, deltaTime)) {
GetComponent<PhotonView>().RPC("startShieldRegen", PhotonTargets.All);
}
}
[PunRPC]
IEnumerator startShieldRegen() {
if (isCoroutineExecuting) {
yield break;
}
isCoroutineExecuting = true;
yield return new WaitForSeconds(2f);
localPlayer_ShieldBar.fillAmount += 0.15f;
localPlayer_ShieldPercentage.text = (localPlayer_ShieldBar.fillAmount * 100).ToString();
otherPlayer_ShieldBar.fillAmount += 0.15f;
if (localPlayer_ShieldBar.fillAmount > 1f)
{
localPlayer_ShieldPercentage.text = "100";
localPlayer_ShieldBar.fillAmount = 1f;
otherPlayer_ShieldBar.fillAmount = 1f;
playerLastTimeHit = 0;
otherLastTimeHit = 0;
isCoroutineExecuting = false;
}
}
Thanks in advance.
Answer by ChristianSimon · Aug 23, 2018 at 09:49 AM
Hi,
the best way might be, to only calculate health regeneration on the owner of the object and send the amount of recovered health by using the RPC. So before handling anything inside the Update function, you should add a if (!photonView.isMine) return;
condition at the beginning of that function. This avoids unnecessary processing on non-owner clients. If the client is the owner of the object, he can start checking, if the character can regenerate health. If it is time to recover some health, the owner of the character can call the RPC and send the amount of recovered health, for example by using photonView.RPC("FunctionName", PhotonTargets.All, amountOfRecoveredHealth);
. You will then need a function, that actually gets called, like this one [PunRPC] void FunctionName(int amount) { }
, where you add the amount of recovered health to the health value.
$$anonymous$$mmmm that's a good strategy now that i think of it. I made the logic work yesterday. I'm only missing one thing which is interruption of health regen to reset the first 8sec delay to start regenerating again. But what happens if i calculate both ? local and other player's health at the same time? is that a bad thing?
In my opinion each object should only calculate values that are relevant for this object. If you are calculating values on multiple clients for multiple the game runs perhaps out of synchronization (happens not necessarily).
So, in other words, you say to maintain the health regen locally, and then send the "update" to other players, sorry i'm new to $$anonymous$$ultiplayer and Unity. $$anonymous$$akes total sense what you say, because it would be stupid to calculate everyone's health locally, imagine if there are 10 players besides you, my phone would be end up calculating everything over and over, which is very consu$$anonymous$$g. Good catch. So after every iteration of my recovery health inside the while loop, after updating the current health/shield... i will be calling this RPC:
photonView.RPC("SendShieldRecoveryDataToOthers", PhotonTargets.Others, shieldBar.fillAmount);
And that function would be like this:
[PunRPC]
private void SendShieldRecoveryDataToOthers(float shield) {
if (!photonView.is$$anonymous$$ine) {
otherPlayer_ShieldBar.fillAmount = shield;
}
}
This is for the shield regen, which is the same as it would be for a health regen, is just my game has both, health and shield. Health won't regen, shield does.
One more hint: since you are using PhotonTargets.Others, you would have to apply the changes made to the health value locally, too. 'Others' in this case means, that this RPC is only called on other clients. If you would use 'All', the RPC would be called on the local client as well. In this case you wouldn't have to apply the changes made to the health value manually since this would be done in the RPC.
Oh mmm that's nice, i could do that too... use All, and everything will pass through the "!photonView.is$$anonymous$$ine" validation. RIght?
Nice! it works, and i think it's waaaay better this way too. Thanks for the info! I'm still learning :D
Your answer
Follow this Question
Related Questions
How to make jump ball on grounds like game hop on App store? 0 Answers
Communication between Photon Cloud game and web server 0 Answers
what is wrong with this???? game is not restarting when hp is zero 1 Answer
Lerping to Smooth Network Movement 0 Answers
What's wrong with Photon Demoworker Demo synchronization? 1 Answer