Files
survival-game/Assets/Mirror/Examples/PickupsDropsChilds/Scripts/SceneObject.cs
2025-06-16 13:15:42 +00:00

109 lines
3.9 KiB
C#

using System.Collections;
using UnityEngine;
namespace Mirror.Examples.PickupsDropsChilds
{
[RequireComponent(typeof(Rigidbody))]
public class SceneObject : NetworkBehaviour
{
[Header("Prefabs")]
public GameObject ballPrefab;
public GameObject batPrefab;
public GameObject boxPrefab;
[Header("Settings")]
[Range(0, 5)] public float force = 1;
// IMPORTANT: Order of SyncVar declarations is intentional!
// ChangeEquipment coroutine depends on equippedItemConfig being set first
// but equippedItemConfig can also be changed independent of equippedItem
// changing, e.g. reloading usages.
[Header("SyncVars in Specific Order")]
[SyncVar(hook = nameof(OnChangeEquippedItemConfig))]
public EquippedItemConfig equippedItemConfig = default;
[SyncVar(hook = nameof(OnChangeEquipment))]
public EquippedItem equippedItem;
[Header("Diagnostics")]
[ReadOnly] public GameObject equippedObject;
[ReadOnly] public Vector3 direction;
// Cached reference to IEquipped component on the child object
[ReadOnly, SerializeField] IEquipped iEquipped;
protected override void OnValidate()
{
if (Application.isPlaying) return;
base.OnValidate();
if (TryGetComponent(out Rigidbody rb))
rb.isKinematic = true;
if (TryGetComponent(out NetworkTransformBase nt))
nt.syncDirection = SyncDirection.ServerToClient;
}
public override void OnStartServer()
{
if (TryGetComponent(out Rigidbody rb))
{
rb.isKinematic = false;
rb.AddForce(direction * force, ForceMode.Impulse);
}
}
void OnMouseDown()
{
NetworkClient.localPlayer.GetComponent<PickupsDropsChilds>().CmdPickupItem(gameObject);
}
void OnChangeEquippedItemConfig(EquippedItemConfig _, EquippedItemConfig newEquippedItemConfig)
{
// equippedItem may be EquippedItem.nothing so check for not null
// before getting reference to the IEquipped interface component
if (equippedObject != null && equippedObject.TryGetComponent(out iEquipped))
if (!iEquipped.equippedItemConfig.Equals(equippedItemConfig))
iEquipped.equippedItemConfig = equippedItemConfig;
}
void OnChangeEquipment(EquippedItem _, EquippedItem newEquippedItem)
{
StartCoroutine(ChangeEquipment());
}
// Since Destroy is delayed to the end of the current frame, we use a coroutine
// to clear out any child objects before instantiating the new one
IEnumerator ChangeEquipment()
{
while (transform.childCount > 0)
{
Destroy(transform.GetChild(0).gameObject);
yield return null;
}
equippedObject = null;
switch (equippedItem)
{
case EquippedItem.ball:
equippedObject = Instantiate(ballPrefab, transform);
break;
case EquippedItem.bat:
equippedObject = Instantiate(batPrefab, transform);
break;
case EquippedItem.box:
equippedObject = Instantiate(boxPrefab, transform);
break;
}
// equippedItem may be EquippedItem.nothing so check for not null
// before getting reference to the IEquipped interface component
// and only set the equippedItemConfig if it's different.
if (equippedObject != null && equippedObject.TryGetComponent(out iEquipped))
if (!iEquipped.equippedItemConfig.Equals(equippedItemConfig))
iEquipped.equippedItemConfig = equippedItemConfig;
}
}
}