您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
111 行
3.8 KiB
111 行
3.8 KiB
using Unity.Multiplayer.Samples.Utilities;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.Multiplayer.Samples.BossRoom.Visual
|
|
{
|
|
[RequireComponent(typeof(NetcodeHooks))]
|
|
public class ClientProjectileVisualization : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
[Tooltip("Explosion prefab used when projectile hits enemy. This should have a fixed duration.")]
|
|
SpecialFXGraphic m_OnHitParticlePrefab;
|
|
|
|
[SerializeField]
|
|
TrailRenderer m_TrailRenderer;
|
|
|
|
NetworkProjectileState m_NetState;
|
|
|
|
Transform m_Parent;
|
|
|
|
const float k_LerpTime = 0.1f;
|
|
|
|
PositionLerper m_PositionLerper;
|
|
NetcodeHooks m_Hooks;
|
|
|
|
void Awake()
|
|
{
|
|
m_Hooks = GetComponent<NetcodeHooks>();
|
|
m_Hooks.OnNetworkSpawnHook += OnSpawn;
|
|
m_Hooks.OnNetworkDespawnHook += OnDespawn;
|
|
}
|
|
|
|
void OnSpawn()
|
|
{
|
|
if (!NetworkManager.Singleton.IsClient || transform.parent == null)
|
|
{
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
m_TrailRenderer.Clear();
|
|
|
|
m_Parent = transform.parent;
|
|
transform.parent = null;
|
|
m_NetState = m_Parent.GetComponent<NetworkProjectileState>();
|
|
m_NetState.HitEnemyEvent += OnEnemyHit;
|
|
|
|
m_PositionLerper = new PositionLerper(m_Parent.position, k_LerpTime);
|
|
transform.rotation = m_Parent.transform.rotation;
|
|
}
|
|
|
|
void OnDespawn()
|
|
{
|
|
m_TrailRenderer.Clear();
|
|
|
|
if (m_NetState != null)
|
|
{
|
|
transform.parent = m_Parent;
|
|
m_NetState.HitEnemyEvent -= OnEnemyHit;
|
|
}
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
m_Hooks.OnNetworkSpawnHook -= OnSpawn;
|
|
m_Hooks.OnNetworkDespawnHook -= OnDespawn;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (m_Parent == null)
|
|
{
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
// One thing to note: this graphics GameObject is detached from its parent on OnNetworkSpawn. On the host,
|
|
// the m_Parent Transform is translated via ServerProjectileLogic's FixedUpdate method. On all other
|
|
// clients, m_Parent's NetworkTransform handles syncing and interpolating the m_Parent Transform. Thus, to
|
|
// eliminate any visual jitter on the host, this GameObject is positionally smoothed over time. On all other
|
|
// clients, no positional smoothing is required, since m_Parent's NetworkTransform will perform
|
|
// positional interpolation on its Update method, and so this position is simply matched 1:1 with m_Parent.
|
|
|
|
if (NetworkManager.Singleton.IsHost)
|
|
{
|
|
transform.position = m_PositionLerper.LerpPosition(transform.position,
|
|
m_Parent.transform.position);
|
|
}
|
|
else
|
|
{
|
|
transform.position = m_Parent.position;
|
|
}
|
|
}
|
|
|
|
void OnEnemyHit(ulong enemyId)
|
|
{
|
|
//in the future we could do quite fancy things, like deparenting the Graphics Arrow and parenting it to the target.
|
|
//For the moment we play some particles (optionally), and cause the target to animate a hit-react.
|
|
|
|
NetworkObject targetNetObject;
|
|
if (NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(enemyId, out targetNetObject))
|
|
{
|
|
if (m_OnHitParticlePrefab)
|
|
{
|
|
// show an impact graphic
|
|
Instantiate(m_OnHitParticlePrefab.gameObject, transform.position, transform.rotation);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|