Follow-up with new code, as per below answer. Unfornutely i still have it wrong and now the character doesn't animate at all (it seems to stay at 0.00 of the clip for ever or constantly resets to 0.00 in each frame). The code looks a bit lengthy but there's really not that much too it. I appreciate any of you expert folk taking a closer look and would happily buy you a coffee or two via paypal if you can help me out with this mind-boggling problem :S :]
nb. The object has always had an Animator and NetworkAnimator on the parent object. It also has NetworkIdentity and NetworkTransform. The Identity of the player (the object in question) is set to 'Local Player Authority'
new code (not working still!):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class Player_mp : NetworkBehaviour {
public float walkSpeed, sideSpeed, turnSpeed, aimSpeed;
Vector3 inputInWorldSpace;
public Gun currentGun;
public Transform headLookTransform, gunShoulderRestTransform;
public string walkAnim, walkBackAnim, strafeLeftAnim, strafeRightAnim, turnLeftAnim, turnrightAnim, jumpAnim, runAnim, runBackAnim;
public GameObject bulletPrefab;
[SyncVar(hook = "OnAnimChangeSpeed")] float animationSpeed;
[SyncVar(hook = "OnAnimChangeString")] string animationString;
Vector3 velLocalised;
private void Update()
{
if (!isLocalPlayer)
{
return;
}
// QUESTION:: Is this meant to also be a SyncVar????
velLocalised = transform.InverseTransformVector(GetComponent<CharacterController>().velocity);
}
void FixedUpdate () {
if (!isLocalPlayer)
{
return;
}
float mouseX = Input.GetAxis("Mouse X");
float mouseY = Input.GetAxis("Mouse Y");
transform.SetPositionAndRotation(transform.position, Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y + (mouseX * turnSpeed * Time.deltaTime), transform.eulerAngles.z));
if (Input.GetMouseButtonDown(0))
{
CmdFireBullet(); // NOTE::: Note this Command has always worked as I expected to shoot bullets
}
Vector3 inputs = new Vector3(Input.GetAxis("Horizontal") * walkSpeed * Time.deltaTime, 0, Input.GetAxis("Vertical") * sideSpeed * Time.deltaTime);
inputInWorldSpace = transform.TransformVector(inputs);
gunShoulderRestTransform.eulerAngles = new Vector3(gunShoulderRestTransform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
gunShoulderRestTransform.Rotate(mouseY, 0, 0);
if (inputs.z > 0)
{
animationSpeed = velLocalised.z;
}
else if (inputs.z < 0)
{
animationSpeed = velLocalised.z;
CmdChangeAnimString(walkBackAnim);
}
else if (inputs.x > 0)
{
animationSpeed = velLocalised.x;
CmdChangeAnimString(strafeRightAnim);
}
else if (inputs.x < 0)
{
animationSpeed = velLocalised.x;
CmdChangeAnimString(strafeLeftAnim);
}
else
{
animationSpeed = velLocalised.z;
}
OnAnimChangeSpeed(animationSpeed);
OnAnimChangeString(animationString);
}
private void LateUpdate()
{
if (!isLocalPlayer)
{
return;
}
GetComponent<CharacterController>().Move(inputInWorldSpace);
}
[Command] // Handles Firing Bullets..
void CmdFireBullet()
{
GameObject bullet = Instantiate(bulletPrefab);
NetworkServer.Spawn(bullet);
Vector3 bulletForce = currentGun.transform.forward * currentGun.bulletForce;
bullet.GetComponent<Bullet>().Fire(currentGun.bulletSpawn.transform.position, currentGun.bulletSpawn.transform.eulerAngles, bulletForce);
}
// Functions to change animation speed per client as per it's character controllers velocity....
void OnAnimChangeSpeed(float speed)
{
Debug.Log("anim speed change detected");
CmdChangeAnimSpeed(speed);
}
[Command]
void CmdChangeAnimSpeed(float animSpeed)
{
RpcChangeAnimSpeed(animSpeed);
}
[ClientRpc]
void RpcChangeAnimSpeed(float animSpeed)
{
animSpeed = Mathf.Abs(animSpeed);
Debug.Log("animspeed ABS = " + animSpeed);
GetComponent<Animator>().speed = animSpeed;
Debug.Log("actual animator speed = " + GetComponent<Animator>().speed);
}
// These functions will change the string of the current animation and use it to call anim.Play(string) when called upon.
void OnAnimChangeString(string animName)
{
CmdChangeAnimString(animName);
}
[Command]
void CmdChangeAnimString(string clipName)
{
SwitchCurrentAnimation(clipName);
}
void SwitchCurrentAnimation(string clipName)
{
RpcChangeAnimString(clipName);
}
[ClientRpc]
void RpcChangeAnimString(string clipName)
{
// QUESTION::: Does 'anim' need to be a SyncVar?????
GetComponent<Animator>().Play(clipName);
}
// This is purely for the Hand to Gun IK (working already) it makes hands hold gun correctly....
private void OnAnimatorIK(int layerIndex)
{
GetComponent<Animator>().SetIKPosition(AvatarIKGoal.LeftHand, currentGun.leftGrip.position);
GetComponent<Animator>().SetIKPositionWeight(AvatarIKGoal.LeftHand, 1.0f);
GetComponent<Animator>().SetIKPosition(AvatarIKGoal.RightHand, currentGun.rightGrip.position);
GetComponent<Animator>().SetIKPositionWeight(AvatarIKGoal.RightHand, 1.0f);
GetComponent<Animator>().SetLookAtPosition(headLookTransform.position);
GetComponent<Animator>().SetLookAtWeight(1.0f, 0f);
}
}
ORIGINAL QUESTION:
Hello again I am attempting to make a very basic multiplayer networked game using Unity. Right now to keep it fairly simple I just want to be able to have multiple players join the world and be able to walk around.
My problem arises because I am using the velocity of the player to adjust the animation speed. So if the player isn't moving the animation speed is 0, etc.
At one point i thought i had it working with ClientRPC calls, but I have since written more code (I added side stepping as well as forward backwards animations) and it seems to not work again.
The current code seems to be working great for the local client but not at all changing the animation speed on the remote clients, it just stays at 1.0f.
I'd be very grateful if someone can look at this code and tell me what I've done wrong. I've made this error and been stuck at this very point on other projects I've worked on. Heres the code. Thanks!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class Player_mp : NetworkBehaviour {
CharacterController characterCont;
Animator anim;
public float walkSpeed, sideSpeed, turnSpeed, aimSpeed;
Vector3 inputInWorldSpace;
public Gun currentGun;
public Transform headLookTransform, gunShoulderRestTransform;
public string walkAnim, walkBackAnim, strafeLeftAnim, strafeRightAnim, turnLeftAnim, turnrightAnim, jumpAnim, runAnim, runBackAnim;
public GameObject bulletPrefab;
float animationSpeed;
Vector3 velLocalised;
public override void OnStartClient()
{
characterCont = GetComponent<CharacterController>();
anim = GetComponent<Animator>();
}
void FixedUpdate () {
if (!isLocalPlayer)
{
return;
}
float mouseX = Input.GetAxis("Mouse X");
float mouseY = Input.GetAxis("Mouse Y");
transform.SetPositionAndRotation(transform.position, Quaternion.Euler(transform.eulerAngles.x, transform.eulerAngles.y + (mouseX * turnSpeed * Time.deltaTime), transform.eulerAngles.z));
if (Input.GetMouseButtonDown(0))
{
CmdFireBullet();
}
Vector3 inputs = new Vector3(Input.GetAxis("Horizontal") * walkSpeed * Time.deltaTime, 0, Input.GetAxis("Vertical") * sideSpeed * Time.deltaTime);
inputInWorldSpace = transform.TransformVector(inputs);
gunShoulderRestTransform.eulerAngles = new Vector3(gunShoulderRestTransform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
gunShoulderRestTransform.Rotate(mouseY, 0, 0);
velLocalised = transform.InverseTransformVector(characterCont.velocity);
if (isServer)
{
// select current clip depending on input (would rather do it by the velocity if i could get it to work!):
if (inputs.z > 0)
{
animationSpeed = velLocalised.z;
RpcSetAnimClip(walkAnim);
}
else if (inputs.z < 0)
{
animationSpeed = velLocalised.z;
RpcSetAnimClip(walkBackAnim);
}
else if (inputs.x > 0)
{
animationSpeed = velLocalised.x;
RpcSetAnimClip(strafeRightAnim);
}
else if (inputs.x < 0)
{
animationSpeed = velLocalised.x;
RpcSetAnimClip(strafeLeftAnim);
}
else
{
animationSpeed = velLocalised.z;
}
RpcSetAnimSpeed(animationSpeed);
}
}
private void LateUpdate()
{
if (!isLocalPlayer)
{
return;
}
characterCont.Move(inputInWorldSpace);
}
[Command]
void CmdFireBullet()
{
GameObject bullet = Instantiate(bulletPrefab);
NetworkServer.Spawn(bullet);
Vector3 bulletForce = currentGun.transform.forward * currentGun.bulletForce;
bullet.GetComponent<Bullet>().Fire(currentGun.bulletSpawn.transform.position, currentGun.bulletSpawn.transform.eulerAngles, bulletForce);
}
[ClientRpc]
void RpcSetAnimSpeed(float animSpeed)
{
if (animSpeed < 0)
{
animSpeed *= -1;
}
anim.speed = animSpeed;
}
[ClientRpc]
void RpcSetAnimClip(string clipName)
{
anim.Play(clipName);
}
[ClientRpc]
void RpcSetAnimSpeedAndClip(float animSpeed, string clipName)
{
if (animSpeed < 0)
{
animSpeed *= -1;
}
anim.speed = animSpeed;
anim.Play(clipName);
}
private void OnAnimatorIK(int layerIndex)
{
anim.SetIKPosition(AvatarIKGoal.LeftHand, currentGun.leftGrip.position);
anim.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1.0f);
anim.SetIKPosition(AvatarIKGoal.RightHand, currentGun.rightGrip.position);
anim.SetIKPositionWeight(AvatarIKGoal.RightHand, 1.0f);
anim.SetLookAtPosition(headLookTransform.position);
anim.SetLookAtWeight(1.0f, 0f);
}
}