我正在嘗試創建一個多人 TPS,在其中我在本地(在我的編輯器中)實體化一個子彈并對其施加力。一旦它擊中其他玩家,我想稱該玩家為 TakeDamage RPC。
可悲的是,我遇到了這個我無法修復的奇怪錯誤訊息(已經花了我幾天的時間)。
我的彈丸腳本:
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Arrow : MonoBehaviour
{
[SerializeField] float timeToDestroy;
[SerializeField] ParticleSystem hitEffect;
[SerializeField] TrailRenderer trailRenderer;
float timer;
private Rigidbody rb;
private Collider col;
private void Awake()
{
rb = GetComponent<Rigidbody>();
col = GetComponent<Collider>();
}
private void Update()
{
timer = Time.deltaTime;
if (timer > timeToDestroy) Destroy(gameObject);
}
private void OnCollisionEnter(Collision collision)
{
rb.isKinematic = true;
rb.velocity = Vector3.zero;
trailRenderer.enabled = false;
ShowHitEffect(collision.GetContact(0));
col.enabled = false;
if (collision.gameObject.CompareTag("Player"))
{
rb.isKinematic = true;
rb.velocity = Vector3.zero;
trailRenderer.enabled = false;
PhotonView pv = collision.gameObject.GetPhotonView();
Debug.Log("hit " pv.Controller.NickName);
pv.RPC("DealDamage", RpcTarget.All, PhotonNetwork.LocalPlayer.NickName, .5f, PhotonNetwork.LocalPlayer.ActorNumber);
}
Destroy(gameObject, 2f);
}
private void ShowHitEffect(ContactPoint cp)
{
hitEffect.transform.position = cp.point;
hitEffect.transform.forward = cp.normal;
hitEffect.Emit(1);
}
}
武器控制器腳本
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponController : MonoBehaviourPunCallbacks
{
[Header("Fire Rate")]
[SerializeField] float fireRate;
float fireRateTimer;
[SerializeField] bool semiAuto;
[Header("Bullet Property")]
[SerializeField] GameObject bullet;
[SerializeField] Transform barrelPos;
[SerializeField] float bulletVelocity;
[SerializeField] byte bulletPerShot;
public AimController aim;
[SerializeField] AudioClip gunshot;
public AudioSource audioSource;
public WeaponAmmo ammo;
public ParticleSystem muzzleFlash;
public ParticleSystem hitEffect;
// Start is called before the first frame update
void Start()
{
fireRateTimer = fireRate;
}
private void Update()
{
if (!photonView.IsMine) return;
if (ShouldFire()) Fire();
}
bool ShouldFire()
{
fireRateTimer = Time.deltaTime;
if (fireRateTimer < fireRate) return false;
if (ammo.currentAmmo == 0) return false;
if (semiAuto && Input.GetKeyDown(KeyCode.Mouse0)) return true;
if (!semiAuto && Input.GetKey(KeyCode.Mouse0)) return true;
return false;
}
[PunRPC]
private void EmitMuzzleFlash()
{
muzzleFlash.Emit(1);
}
void Fire()
{
fireRateTimer = 0;
barrelPos.LookAt(aim.actualAimPos);
audioSource.PlayOneShot(gunshot);
EmitMuzzleFlash();
//photonView.RPC("EmitMuzzleFlash", RpcTarget.All);
ammo.currentAmmo--;
for (int i = 0; i < bulletPerShot; i )
{
GameObject currentBullet = Instantiate(bullet, barrelPos.position, barrelPos.rotation);
Rigidbody rigidbody = currentBullet.GetComponent<Rigidbody>();
rigidbody.AddForce(barrelPos.forward * bulletVelocity, ForceMode.Impulse);
// Projectile Instantiate
/*{
GameObject currentProjectile = (GameObject)PhotonNetwork.Instantiate(bullet.name, barrelPos.position, barrelPos.rotation);
Rigidbody rb = currentProjectile.GetComponent<Rigidbody>();
rb.AddForce(barrelPos.forward * bulletVelocity, ForceMode.Impulse);
}*/
}
}
}
播放器控制器腳本(rpc 所在的位置)
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviourPunCallbacks
{
private PlayerStats stats = new PlayerStats();
void Start()
{
if (photonView.IsMine)
{
UIController.instance.healthSlider.maxValue = stats.maxHealth;
UIController.instance.healthSlider.value = stats.GetCurrentHealth();
}
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
FocusWindows();
}
void FocusWindows()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
Cursor.lockState = CursorLockMode.None;
}
else if (Cursor.lockState == CursorLockMode.None)
{
if (Input.GetMouseButton(0))
{
Cursor.lockState = CursorLockMode.Locked;
}
}
}
#region
[PunRPC]
public void DealDamage(string damager, float damageAmount, int actor)
{
Debug.Log("called rpc deal damage");
Debug.Log("damager " damager " damageAmount " damageAmount " actor " actor);
TakeDamage(damager, damageAmount, actor);
}
public void TakeDamage(string damager, float damageAmount, int actor)
{
if (photonView.IsMine)
{
stats.ReduceHealth(damageAmount);
if (stats.GetCurrentHealth() == 0)
{
PlayerSpawner.Instance.Die(damager);
MatchManager.instance.UpdateStatSend(actor, 0, 1);
}
UIController.instance.healthSlider.value = stats.GetCurrentHealth();
}
}
#endregion
}
Projectile Prefab(resource) 在此處輸入影像描述
播放器預制件 在此處輸入影像描述
奇怪的是,如果我使用“網路中的實體化箭頭”,則會呼叫 rpc。但這并不理想,因為它會在每次飛行時發送彈丸的變換。因此,我只想檢查本地(沒有 photonView 的箭頭)是否擊中敵人,然后呼叫該敵人的 rpc 以使他受到傷害并可能顯示來自損壞者的假專案。如果我的方法是幼稚/錯誤的,請告訴我一個更好的方法。
uj5u.com熱心網友回復:
如@derHugo 所述,我在 photonView 所在的同一腳本上轉移了 rpc 呼叫。我認為主要問題是我對 RPC 的理解。我認為 rpc 就像一個公共方法,您可以在其中呼叫它。我想我需要重新閱讀有關 rpc 和引發事件的檔案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/508679.html
標籤:unity3d光子