Hello, I know this post is very long and boring, so I thank you in advance for reading.
I just started implementing uNet (multiplayer) in my game.
I can’t seem to call an external method from the host client to the remote client (the non server client). I expect it has something to do with authority.
Any help would be very appreciated!
How the project is setup:
The game is a sidescrolling 2D game, where players hit eachother with melee attacks (swords).
How I have setup my players:
The players have 4x vital components on it:
- A PlayerController (which derives from NetworkBehaviour),
- A StatHandler (which also derives from NetworkBehaviour),
- and a NetworkIdentity+NetworkTransform component.
- On the hand of the player (a child of the player, where the sword is), I have another script called AttackCollider (not deriving from Network Behaviour), which simply check if you have hit another player. I have a BoxCollider2D on the same child (hand).
My scripts + explanations:
When this player (hereby called: player) hits another player (hereby called: enemy), he will execute a TakeDamage-method on the other player, by first sending the enemy hit to the players playercontroller.
The playercontroller refers to the enemy’s playercontroller and does the TakeDamage method.
The enemy’s TakeDamage-method updates the health (in stathandler) and updates animations on the enemy.
Let’s look at the AttackCollider script which sits on the sword:
public class AttackCollider : MonoBehaviour
{
//The attack collider of the player
public Collider2D weaponTrigger;
[Client]
void OnTriggerEnter2D(Collider2D collision)
{
if (!playerNet.isLocalPlayer)
return;
if (collision.gameObject.name != transform.root.name && collision.gameObject.tag == "Player") {
//Checks if the gameobject hit has the StatHandler component
var idamage = collision.gameObject.GetComponent<StatHandler>();
if (idamage != null)
{
//Executes a Command on THIS gameobject
playerController.CmdDamageEnemy(10, collision.gameObject.GetComponent<NetworkIdentity>());
}
}
}
First I have to refer to the playercontroller which is on the same gameobject as the player. Because PlayerController derives from Networkehaviour. Then the playercontroller will execute the TakeDamage-method on the enemy:
public class PlayerController : NetworkBehaviour
{
//This method is executed on the player by the AttackCollider
[Command]
public void CmdDamageEnemy(float damage, NetworkIdentity networkId)
{
//Get the PlayerController of the enemy and executes TakeDamage
networkId.GetComponent<PlayerController>().TakeDamage(10);
}
//Take damage is only executed on the enemy
public void TakeDamage(float damage)
{
//First we add some animations and some knockback movement, THIS IS WHAT DOESN'T WORK on the host-client
animator.SetFloat("Hurt");
rigidBody.AddForce(Vector2.right * hitForce, ForceMode2D.Force);
//Then we update the HP of the enemy
CmdUpdateHealth(damage);
}
[Command]
void CmdUpdateHealth(float damage)
{
//Updates the HP in the StatHandler.... THIS WORKS ON BOTH CLIENTS BTW!!
statHandler.CmdUpdateHealth(damage);
}
}
Then we update the Health in the StatHandler:
public class StatHandler : NetworkBehaviour
{
[SyncVar(hook = "UpdateHealthbar")]
public float currentHealth;
[SerializeField]
public float maxHealth = 100;
//Updates the SyncVar (currentHealth), executed from PlayerController
[Command]
public void CmdUpdateHealth(float amount)
{
if (!isServer)
return;
currentHealth -= amount;
}
//The syncVar automatically executes this method, which updates the healthbar, THIS WORKS btw!
private void UpdateHealthbar(float amount)
{
healthBar.fillAmount = amount / maxHealth;
}
}
Okey, I know this was a lot to dig in. But I just wanted to give you all the lines of code that has something to do with this issue.
So the issue here is: Everything works when the remote (non-host) client hits the host-client. But when the host-client tries to hit the remote client, only the health is updated, but the animation + addforce lines doesn’t look like they get executed (this is not true actually, keep reading).
If I HAVE NOT touched anything (movement/actions input) on the remote client. Everything works perfectly and there’s no issue. But if I HAVE touched any input, and then do damage to it, the position just “stutters” for 1 millisecond, and then go back to normal. Almost as if the remote client calls the animation+addforce lines, but then goes back to the anim-state+position that was previously set locally on that client.
Sorry for the long wall of text. Been sitting on this issue for the past days. Been trying to read up on uNet. But just can’t figure it out
Any help is sooooo greatly appreciated! I am desperate.
Much love, Simon