Как управлять анимацией перехода статического объекта в единый мультиплеер
Я хочу, чтобы анимация статического объекта, который находится в среде многопользовательского единства, должна происходить, когда игрок нажимает на нее. а также анимация будет показывать каждый игрок, который подключен к серверу
public class AnimationCtr : NetworkBehaviour
{
Animator anim;
bool canSpawn;
int count;
[SyncVar]
bool flag;
// Use this for initialization
void Start ()
{
anim = GetComponent<Animator>();
flag = false;
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 100.0f))
{
if (hit.transform.gameObject.name.Equals("door") && (!flag))
{
// anim.SetInteger("btnCount", 2);
Debug.Log(hit.transform.gameObject.name);
anim.SetInteger("btnCount", 2);
flag = true;
}
else if (hit.transform.gameObject.name.Equals("door")&& (flag))
{
anim.SetInteger("btnCount", 3);
flag = false;
}
}
}
}
}
1 ответ
Одна проблема в том, что вы не можете установить [Synvar]
на стороне клиента.
От [SyncVar]
документ:
Эти переменные будут синхронизированы со своими серверами с клиентами
Я бы также позволил серверу решить, является ли текущее значение flag
является true
или же false
,
public class AnimationCtr : NetworkBehaviour
{
Animator anim;
bool canSpawn;
int count;
// no need for sync ar since flag is only needed on the server
bool flag;
// Use this for initialization
void Start ()
{
anim = GetComponent<Animator>();
flag = false;
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (!Physics.Raycast(ray, out hit, 100.0f)) return
if (!hit.transform.gameObject.name.Equals("door")) return;
// only check if it is a door
// Let the server handel the rest
CmdTriggerDoor();
}
}
// Command is called by clients but only executed on the server
[Command]
private void CmdTriggerDoor()
{
// this will only happen on the Server
// set the values on the server itself
// get countValue depending on flag on the server
var countValue = flag? 3 : 2;
// set animation on the server
anim.SetInteger("btnCount", countValue);
// invert the flag on the server
flag = !flag;
//Now send the value to all clients
// no need to sync the flag as the decicion is made only by server
RpcSetBtnCount(countValue);
}
// ClientRpc is called by the server but executed on all clients
[ClientRpc]
private void RpcSetBtnCount(int countValue)
{
// This will happen on ALL clients
// Skip the server since we already did it for him it the Command
// For the special case if you are host -> server + client at the same time
if (isServer) return;
// set the value on the client
anim.SetInteger("btnCount", countValue);
}
}
Хотя, если вы хотите анимировать, только если дверь открыта или закрыта, я бы лучше использовал bool parameter
например isOpen
в animator
и просто измените это вместо (animator.SetBool()
). И есть два перехода между двумя состояниями:
Default -> State_Closed -- if "isOpen"==true --> State_Open
<-- if "isOpen"==false --
В ваших анимациях вы просто сохраняете 1 единственный ключевой кадр с целевой позицией. Чем на переходе вы можете установить продолжительность перехода -> сколько времени занимает дверь, чтобы открыть / закрыть (они могут даже отличаться).