MasterOX 水
MasterOX 水5mo ago

hp update problem

ok so ive been trying to get this to work for 5 hours
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Normal.Realtime;
public class playerHealthSync : RealtimeComponent<playerHealthModel> {
public int health = 20;
public Realtime rt;
public Transform spawn1;
public Transform spawn2;
public GameObject player;

protected override void OnRealtimeModelReplaced(playerHealthModel previousModel, playerHealthModel currentModel) {
if (previousModel != null) {
previousModel.hpDidChange -= HpDidChange;
}
if (currentModel != null) {
if (currentModel.isFreshModel){
currentModel.hp = health;
}
UpdateHp();
currentModel.hpDidChange += HpDidChange;
}
}
private void HpDidChange(playerHealthModel model, int value) {
UpdateHp();
}
private void UpdateHp() {
print("updated hp");
health= model.hp;
}
public void SetHp(int hp) {
print("set hp");
model.hp = hp;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Normal.Realtime;
public class playerHealthSync : RealtimeComponent<playerHealthModel> {
public int health = 20;
public Realtime rt;
public Transform spawn1;
public Transform spawn2;
public GameObject player;

protected override void OnRealtimeModelReplaced(playerHealthModel previousModel, playerHealthModel currentModel) {
if (previousModel != null) {
previousModel.hpDidChange -= HpDidChange;
}
if (currentModel != null) {
if (currentModel.isFreshModel){
currentModel.hp = health;
}
UpdateHp();
currentModel.hpDidChange += HpDidChange;
}
}
private void HpDidChange(playerHealthModel model, int value) {
UpdateHp();
}
private void UpdateHp() {
print("updated hp");
health= model.hp;
}
public void SetHp(int hp) {
print("set hp");
model.hp = hp;
}
}
this is the script that syncs the health, evey player has it attatched to them and this is the thing that updates the health
if(canHit && coll.tag=="MPPlayer")
{
coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>().ClearOwnership();
coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>().SetHp(coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>().health-damagePlayer);
}
if(canHit && coll.tag=="MPPlayer")
{
coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>().ClearOwnership();
coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>().SetHp(coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>().health-damagePlayer);
}
what happens is: if i attack the other player with the sword, its health updates on my screen but not on their screen if i attack myself with the sword, my hp updates on both screens, as it should. whats the problem
14 Replies
kapa.ai
kapa.ai5mo ago
Hi @MasterOX 水. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The issue you're experiencing seems to be related to the ownership of the RealtimeView component. In Normcore, the ownership of a RealtimeView determines which client has the authority to make changes to the data. When you attack another player, you're clearing the ownership of their RealtimeView and then trying to update their health. However, since you've just cleared the ownership, no client has the authority to make changes, which is likely why the health update isn't being reflected on the other player's screen. Instead of clearing the ownership, you should request ownership before making changes. Here's how you can modify your code:
if(canHit && coll.tag=="MPPlayer")
{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();
var realtimeView = coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>();

// Request ownership
realtimeView.RequestOwnership();

// Update health
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}
if(canHit && coll.tag=="MPPlayer")
{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();
var realtimeView = coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>();

// Request ownership
realtimeView.RequestOwnership();

// Update health
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}
This way, you're requesting ownership of the RealtimeView before making changes to the health. Once you have ownership, you should be able to update the health and have it reflected on all clients. Remember, when you're done making changes, it's a good practice to clear the ownership if you no longer need it. You can do this by calling realtimeView.ClearOwnership(). For more information on ownership in Normcore, you can refer to the RealtimeView reference (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeView) and the RealtimeView Programming Interface (https://normcore.io/documentation/realtime/realtimeview#programming-interface) in the documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@758040514678489279> kapa.ai is still learning and improving, please let us know how it did by reacting below
MasterOX 水
MasterOX 水OP5mo ago
it didnt work... @Normcore Assistant that gives the same result, i added some debugging logs
if(canHit && coll.tag == "MPPlayer")
{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();
var realtimeView = coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>();

if(!realtimeView.isOwnedLocallySelf)
{
realtimeView.RequestOwnership();
print("ownership requested");
}

if(realtimeView.isOwnedLocallySelf)
{
print("ownership granted");
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}

}
if(canHit && coll.tag == "MPPlayer")
{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();
var realtimeView = coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>();

if(!realtimeView.isOwnedLocallySelf)
{
realtimeView.RequestOwnership();
print("ownership requested");
}

if(realtimeView.isOwnedLocallySelf)
{
print("ownership granted");
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}

}
and ownership is being granted, but again if i attack the other player with the sword, its health updates on my screen but not on their screen. but if i attack myself with the sword, my hp updates on both screens, as it should
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The issue you're experiencing might be due to the fact that the RealtimeView ownership request is not instantaneous. It's a network operation that might take some time to complete. Therefore, when you check realtimeView.isOwnedLocallySelf immediately after realtimeView.RequestOwnership(), it might still return false. To handle this, you can use the DidRequestOwnership and DidReceiveOwnership events provided by the RealtimeView class. Here's how you can modify your code:
if(canHit && coll.tag=="MPPlayer")
{{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();
var realtimeView = coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>();

// Request ownership
realtimeView.RequestOwnership();
print("ownership requested");

// Add event handlers
realtimeView.didRequestOwnership += DidRequestOwnership;
realtimeView.didReceiveOwnership += DidReceiveOwnership;
}}

private void DidRequestOwnership(RealtimeView realtimeView)
{{
print("ownership requested");
}}

private void DidReceiveOwnership(RealtimeView realtimeView)
{{
print("ownership granted");
var playerHealthSync = realtimeView.gameObject.GetComponent<playerHealthSync>();
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}}
if(canHit && coll.tag=="MPPlayer")
{{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();
var realtimeView = coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>();

// Request ownership
realtimeView.RequestOwnership();
print("ownership requested");

// Add event handlers
realtimeView.didRequestOwnership += DidRequestOwnership;
realtimeView.didReceiveOwnership += DidReceiveOwnership;
}}

private void DidRequestOwnership(RealtimeView realtimeView)
{{
print("ownership requested");
}}

private void DidReceiveOwnership(RealtimeView realtimeView)
{{
print("ownership granted");
var playerHealthSync = realtimeView.gameObject.GetComponent<playerHealthSync>();
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}}
In this code, DidRequestOwnership will be called when ownership is requested, and DidReceiveOwnership will be called when ownership is granted. This way, you're ensuring that the health update only happens after ownership has been granted. Remember to remove these event handlers when they're no longer needed to prevent memory leaks. You can do this by calling realtimeView.didRequestOwnership -= DidRequestOwnership; and realtimeView.didReceiveOwnership -= DidReceiveOwnership;. For more information on ownership in Normcore, you can refer to the RealtimeView reference (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeView) and the RealtimeView Programming Interface (https://normcore.io/documentation/realtime/realtimeview#programming-interface) in the documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@758040514678489279> kapa.ai is still learning and improving, please let us know how it did by reacting below
MasterOX 水
MasterOX 水OP5mo ago
@Normcore Assistant 'RealtimeView' does not contain a definition for 'didRequestOwnership' and no accessible extension method 'didRequestOwnership' accepting a first argument of type 'RealtimeView' could be found (are you missing a using directive or an assembly reference?) 'RealtimeView' does not contain a definition for 'didReceiveOwnership' and no accessible extension method 'didReceiveOwnership' accepting a first argument of type 'RealtimeView' could be found (are you missing a using directive or an assembly reference?)
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I apologize for the confusion. It seems I made a mistake. The RealtimeView class in Normcore does not provide didRequestOwnership and didReceiveOwnership events. However, the RealtimeView class does provide an ownerIDSelfDidChange event which is dispatched when the ownerIDSelf value changes. You can use this event to check if the ownership has been granted to the local client. Here's how you can modify your code:
if(canHit && coll.tag=="MPPlayer")
{{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();
var realtimeView = coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>();

// Request ownership
realtimeView.RequestOwnership();
print("ownership requested");

// Add event handler
realtimeView.ownerIDSelfDidChange += OwnerIDSelfDidChange;
}}

private void OwnerIDSelfDidChange(RealtimeView realtimeView, int ownerID)
{{
if(realtimeView.isOwnedLocallySelf)
{{
print("ownership granted");
var playerHealthSync = realtimeView.gameObject.GetComponent<playerHealthSync>();
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}}
}}
if(canHit && coll.tag=="MPPlayer")
{{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();
var realtimeView = coll.gameObject.transform.GetChild(0).GetComponent<RealtimeView>();

// Request ownership
realtimeView.RequestOwnership();
print("ownership requested");

// Add event handler
realtimeView.ownerIDSelfDidChange += OwnerIDSelfDidChange;
}}

private void OwnerIDSelfDidChange(RealtimeView realtimeView, int ownerID)
{{
if(realtimeView.isOwnedLocallySelf)
{{
print("ownership granted");
var playerHealthSync = realtimeView.gameObject.GetComponent<playerHealthSync>();
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}}
}}
In this code, OwnerIDSelfDidChange will be called when the ownerIDSelf value changes. If the RealtimeView is owned by the local client, the health update will be performed. Remember to remove this event handler when it's no longer needed to prevent memory leaks. You can do this by calling realtimeView.ownerIDSelfDidChange -= OwnerIDSelfDidChange;. For more information on ownership in Normcore, you can refer to the RealtimeView reference (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeView) and the RealtimeView Programming Interface (https://normcore.io/documentation/realtime/realtimeview#programming-interface) in the documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@758040514678489279> kapa.ai is still learning and improving, please let us know how it did by reacting below
MasterOX 水
MasterOX 水OP5mo ago
@Normcore Assistant still says ownership granted... but health doesnt update on both screens. i dont think ownership is the problem
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- I see, it seems like the issue might not be related to ownership. Let's try a different approach. In Normcore, the RealtimeComponent class provides a RequestOwnership() method that you can use to request ownership of the model. This might be useful in your case since you're trying to modify the health value which is part of the playerHealthSync model. Here's how you can modify your code:
if(canHit && coll.tag=="MPPlayer")
{{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();

// Request ownership
playerHealthSync.RequestOwnership();
print("ownership requested");

// Update health
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}}
if(canHit && coll.tag=="MPPlayer")
{{
var playerHealthSync = coll.gameObject.transform.GetChild(0).GetComponent<playerHealthSync>();

// Request ownership
playerHealthSync.RequestOwnership();
print("ownership requested");

// Update health
playerHealthSync.SetHp(playerHealthSync.health - damagePlayer);
}}
In this code, you're requesting ownership of the playerHealthSync model before making changes to the health. Once you have ownership, you should be able to update the health and have it reflected on all clients. Remember, when you're done making changes, it's a good practice to clear the ownership if you no longer need it. You can do this by calling playerHealthSync.ClearOwnership(). For more information on ownership in Normcore, you can refer to the RealtimeModel reference (https://normcore.io/documentation/reference/classes/Normal.Realtime.RealtimeModel) in the documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@758040514678489279> kapa.ai is still learning and improving, please let us know how it did by reacting below
MasterOX 水
MasterOX 水OP5mo ago
no, still not fixed. can anyone help me please? ownership is being granted but it only works if i'm attacking myself
MasterOX 水
MasterOX 水OP5mo ago
ty! looking into it now oh. it makes sense now