问题描述
我正在使用镜像开发 RTS 游戏,但遇到了问题。 我正在研究单位的自动攻击功能。 一切都适用于主机,但不适用于客户端。 任何帮助将不胜感激,我已经在这几天了.. 帮助! 或者至少在这里指出我正确的方向。 稍后我会更好地优化它,我只需要了解为什么它在客户端上不起作用。我还注意到客户端会将自己添加到敌人列表中,它似乎忽略了“hasAuthority”检查
写的有点多,所以我会尽量让它更容易理解。
Unit 被实例化,这是附加到它的脚本:
import 'firebase/analytics'
接下来是ArrayDetect函数 使用 Physics.OverlapSphere 检测单元,确保它具有权限并将其添加到敌人对撞机列表中,我还添加了 layerMask 以确保它仅检查单元。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
using System.Linq;
public class UnitFiring : NetworkBehavIoUr
{
[Serializefield] private Targeter targeter = null;
[Serializefield] private GameObject projectilePrefab = null;
[Serializefield] private Transform projectileSpawnPoint = null;
[Serializefield] private float fireRange = 10f;
[Serializefield] private float fireRate = 1f;
[Serializefield] private float rotationSpeed = 20f;
private float lastFireTime;
//auto attack
[Serializefield] private Transform ownaimAtPoint = null;
[Serializefield] private LayerMask layerMask;
[Serializefield] private int updateFunctionFrequency = 60; //in frames
[ServerCallback]
private void Update()
{
if (Time.frameCount % this.updateFunctionFrequency != 0) return;
//runs update every 60 frames
enemyColliders.RemoveAll(Collider => Collider == null);
//if enemyCollider List has GameObject that was destroyed or null,it removes it from the list.
Targetable target = targeter.GetTarget();
if(target == null)
{
ArrayDetect();
AttackUnit();
return;
}
if (!CanFireAtTarget()) { return; }
//look at target
Quaternion targetRotation =
Quaternion.LookRotation(target.transform.position - transform.position);
//Rotate
transform.rotation = Quaternion.Rotatetowards
(transform.rotation,targetRotation,rotationSpeed * Time.deltaTime);
if(Time.time > (1 / fireRate) +lastFireTime)
{
Quaternion projectileRotation = Quaternion.LookRotation(
target.GetaimAtPoint().position - projectileSpawnPoint.position);
GameObject projectileInstance = Instantiate(
projectilePrefab,projectileSpawnPoint.position,projectileRotation);
NetworkServer.Spawn(projectileInstance,connectionToClient);
lastFireTime = Time.time;
}
}
[Client]
private bool CanFireAtTarget()
{
return (targeter.GetTarget().transform.position - transform.position).sqrMagnitude
<= fireRange * fireRange;
}
[Serializefield] private Collider[] colliderArray;
[Serializefield] private List<GameObject> enemyColliders;
现在AttackUnit函数,它会考虑敌人的碰撞器列表并将它们设置为攻击目标
[Server]
private void ArrayDetect()
{
colliderArray = Physics.OverlapSphere(ownaimAtPoint.position,fireRange,layerMask);
foreach (Collider collider in colliderArray)
{
Debug.Log("we hit a",collider);
if (!collider.TryGetComponent<Targetable>(out Targetable potentialTarget))
{
return;
}
if (potentialTarget.hasAuthority)
{
return; //if the hit target is the players,do nothing
}
else
{
enemyColliders = enemyColliders.distinct().ToList();
enemyColliders.Add(collider.gameObject);
Debug.Log("Found an enemy",potentialTarget);
}
}
}
这是 Targetable Script,它只是返回 aimAtPoint:
[ServerCallback]
private void AttackUnit()
{
foreach (GameObject enemy in enemyColliders)
{
Debug.Log("We got confirmed enemy",enemy);
//GetComponent<Targeter>().CmdsetTarget(enemy);
targeter.CmdsetTarget(enemy);
//attack the enemy
}
}
这是 Targeter 脚本中的 CmdsetTarget 命令:
public class Targetable : NetworkBehavIoUr
{
[Serializefield] private Transform aimAtPoint = null;
public Transform GetaimAtPoint()
{
return aimAtPoint;
}
}
这是我在控制台中得到的错误,但只有在客户端单元上,主机才能正常运行:
[Command]
public void CmdsetTarget(GameObject targetGameObject)
{
if(!targetGameObject.TryGetComponent<Targetable>(out Targetable newTarget)) { return; }
//if game object does not have a target,return
target = newTarget;
}
感谢您花时间阅读本文
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)