项目实训(十四)——FPS游戏多人化

一、前言

经过粗略地分工,在FPS游戏多人化的部分,由我来完成pun控制输入同步和remote开枪效果同步。

二、pun控制输入同步

首先要对游戏角色的物体进行一些组件和脚本的装载。
在这里插入图片描述
在这里插入图片描述
对于脚本FPCharacterControllerMovement4,它实现了人物移动的网络同步。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;

public class FPCharacterControllerMovement4 : MonoBehaviour
{
    
    
    private CharacterController characterController;
    [SerializeField] private Animator characterAnimator;
    [SerializeField] private Animator tp_CharacterAnimator;
    private Vector3 movementDirection;
    private Transform characterTransform;
    private float velocity;


    private bool isCrouched;
    private float originHeight;

    public float SprintingSpeed;
    public float WalkSpeed;

    public float SprintingSpeedWhenCrouched;
    public float WalkSpeedWhenCrouched;

    public float Gravity = 9.8f;
    public float JumpHeight;
    public float CrouchHeight = 1f;

    public float CurrentSpeed {
    
     get; private set; }
    private IEnumerator crouchCoroutine;

    private void Start()
    {
    
    
        characterController = GetComponent<CharacterController>();
//        characterAnimator = GetComponentInChildren<Animator>();
        characterTransform = transform;
        originHeight = characterController.height;
    }


    private void Update()
    {
    
    
        CurrentSpeed = WalkSpeed;
        if (characterController.isGrounded)
        {
    
    
            var tmp_Horizontal = Input.GetAxis("Horizontal");
            var tmp_Vertical = Input.GetAxis("Vertical");
            movementDirection =
                characterTransform.TransformDirection(new Vector3(tmp_Horizontal, 0, tmp_Vertical)).normalized;
            if (isCrouched)
            {
    
    
                CurrentSpeed = Input.GetKey(KeyCode.LeftShift) ? SprintingSpeedWhenCrouched : WalkSpeedWhenCrouched;
            }
            else
            {
    
    
                CurrentSpeed = Input.GetKey(KeyCode.LeftShift) ? SprintingSpeed : WalkSpeed;
            }

            if (Input.GetButtonDown("Jump"))
            {
    
    
                movementDirection.y = JumpHeight;
            }

            if (Input.GetKeyDown(KeyCode.C))
            {
    
    
                var tmp_CurrentHeight = isCrouched ? originHeight : CrouchHeight;
                if (crouchCoroutine != null)
                {
    
    
                    StopCoroutine(crouchCoroutine);
                    crouchCoroutine = null;
                }

                crouchCoroutine = DoCrouch(tmp_CurrentHeight);
                StartCoroutine(crouchCoroutine);
                isCrouched = !isCrouched;
            }

            if (characterAnimator != null)
            {
    
    
                characterAnimator.SetFloat("Velocity",
                    CurrentSpeed * movementDirection.normalized.magnitude,
                    0.25f,
                    Time.deltaTime);

                tp_CharacterAnimator.SetFloat("Velocity",
                    CurrentSpeed * movementDirection.normalized.magnitude,
                    0.25f,
                    Time.deltaTime);
                tp_CharacterAnimator.SetFloat("Movement_X", tmp_Horizontal, 0.25f, Time.deltaTime);
                tp_CharacterAnimator.SetFloat("Movement_Y", tmp_Vertical, 0.25f, Time.deltaTime);
            }
        }


        movementDirection.y -= Gravity * Time.deltaTime;
        var tmp_Movement = CurrentSpeed * Time.deltaTime * movementDirection;
        characterController.Move(tmp_Movement);
    }


    private IEnumerator DoCrouch(float _target)
    {
    
    
        float tmp_CurrentHeight = 0;
        while (Mathf.Abs(characterController.height - _target) > 0.1f)
        {
    
    
            yield return null;
            characterController.height =
                Mathf.SmoothDamp(characterController.height, _target,
                    ref tmp_CurrentHeight, Time.deltaTime * 5);
        }
    }

    internal void SetupAnimator(Animator _animator)
    {
    
    
        Debug.Log($"Execute! the animator is empty??? {
      
      _animator == null}");
        characterAnimator = _animator;
    }
}

其中,动画设置如图所示。

在这里插入图片描述

三、remote开枪效果

主要是在WeaponManager脚本中进行了开枪效果的同步。需要进行Photon.Pun以及PunGame.Scripts.Items的引用。

using System;
using System.Collections;
using System.Collections.Generic;
using Photon.Pun;
using PunGame.Scripts.Items;
using UnityEngine;
using UnityEngine.UI;

namespace PunGames.ForthGameScripts.Weapon {
    
     
[System.Serializable]
public class WeaponInfo
{
    
    
    public int WeaponId;
    public string WeaponName;
    public Firearms FP_Weapon;
    public Firearms TP_Weapon;
}


public class WeaponManager : MonoBehaviour
{
    
    
    public Firearms MainWeapon;
    public Firearms SecondaryWeapon;
    public Text AmmoCountTextLabel;

    public Firearms carriedWeapon;

    [SerializeField] private List<WeaponInfo> WeaponInfos;

    [SerializeField] private FPCharacterControllerMovement4 CharacterControllerMovement;

    private AnimatorStateInfo animationStateInfo;
    private IEnumerator waitingForHolsterEndCoroutine;
    public PhotonView photonView;

    public List<Firearms> Arms = new List<Firearms>();
    public Transform WorldCameraTransform;
    public float RaycastMaxDistance = 2;
    public LayerMask CheckItemLayerMask;


    private void UpdateAmmoInfo(int _ammo, int _remaningAmmo)
    {
    
    
        if (AmmoCountTextLabel)
            AmmoCountTextLabel.text = _ammo + "/" + _remaningAmmo;
    }


    private void Start()
    {
    
    
        //......
        // AmmoCountTextLabel = ;
        AmmoCountTextLabel = GameObject.Find("UI").transform.GetChild(6).GetComponent<Text>();
        //photonView = GetComponent<PhotonView>();
        Debug.Log($"Current weapon is null? {
      
      carriedWeapon == null}");
        
        MainWeapon = photonView.IsMine ? WeaponInfos[0].FP_Weapon : WeaponInfos[0].TP_Weapon;


        if (MainWeapon)
        {
    
    
            carriedWeapon = MainWeapon;
            CharacterControllerMovement.SetupAnimator(carriedWeapon.GunAnimator);
        }
    }

    private void Update()
    {
    
    
        if (!photonView.IsMine) return;
        CheckItem();

        if (!carriedWeapon) return;


        SwapWeapon();

        if (Input.GetMouseButton(0))
        {
    
    
            //TODO:hold the Trigger
            Debug.Log("shoot");
           // carriedWeapon.HoldTrigger();
            photonView.RPC("RPC_HoldTrigger", RpcTarget.All);
        }

        if (Input.GetMouseButtonUp(0))
        {
    
    
            //TODO: release the Trigger
           // carriedWeapon.ReleaseTrigger();
            photonView.RPC("RPC_ReleaseTrigger", RpcTarget.All);
        }


        if (Input.GetKeyDown(KeyCode.R))
        {
    
    
            //TODO:Reloading the ammo
           // carriedWeapon.ReloadAmmo();
            photonView.RPC("RPC_ReloadAmmo", RpcTarget.All);
        }

        /*if (Input.GetMouseButtonDown(1))
        {
            //TODO:瞄准
            carriedWeapon.Aiming(true);
        }

        if (Input.GetMouseButtonUp(1))
        {
            //TODO:退出瞄准
            carriedWeapon.Aiming(false);
        }*/

        UpdateAmmoInfo(carriedWeapon.GetCurrentAmmo, carriedWeapon.GetCurrentMaxAmmoCarried);
    }


    private void CheckItem()
    {
    
    
        bool tmp_IsItem = Physics.Raycast(WorldCameraTransform.position,
            WorldCameraTransform.forward,
            out RaycastHit tmp_RaycastHit,
            RaycastMaxDistance, CheckItemLayerMask);


        if (tmp_IsItem)
        {
    
    
            if (Input.GetKeyDown(KeyCode.E))
            {
    
    
                bool tmp_HasItem = tmp_RaycastHit.collider.TryGetComponent(out BaseItem tmp_BaseItem);
                if (tmp_HasItem)
                {
    
    
                    PickupWeapon(tmp_BaseItem);
                    PickupAttachment(tmp_BaseItem);
                }
            }
        }
    }


    private void PickupWeapon(BaseItem _baseItem)
    {
    
    
        if (!(_baseItem is FirearmsItem tmp_FirearmsItem)) return;
        foreach (Firearms tmp_Arm in Arms)
        {
    
    
            if (tmp_FirearmsItem.ArmsName.CompareTo(tmp_Arm.name) != 0) continue;
            switch (tmp_FirearmsItem.CurrentFirearmsType)
            {
    
    
                case FirearmsItem.FirearmsType.AssultRefile:
                    MainWeapon = tmp_Arm;
                    break;
                case FirearmsItem.FirearmsType.HandGun:
                    SecondaryWeapon = tmp_Arm;

                    break;
            }

            SetupCarriedWeapon(tmp_Arm);
        }
    }


    private void PickupAttachment(BaseItem _baseItem)
    {
    
    
        if (!(_baseItem is AttachmentItem tmp_AttachmentItem)) return;

        switch (tmp_AttachmentItem.CurrentAttachmentType)
        {
    
    
            case AttachmentItem.AttachmentType.Scope:
                foreach (ScopeInfo tmp_ScopeInfo in carriedWeapon.ScopeInfos)
                {
    
    
                    if (tmp_ScopeInfo.ScopeName.CompareTo(tmp_AttachmentItem.ItemName) != 0)
                    {
    
    
                        tmp_ScopeInfo.ScopeGameObject.SetActive(false);
                        continue;
                    }

                    tmp_ScopeInfo.ScopeGameObject.SetActive(true);
                    carriedWeapon.BaseIronSight.ScopeGameObject.SetActive(false);
                    carriedWeapon.SetupCarriedScope(tmp_ScopeInfo);
                }

                break;
            case AttachmentItem.AttachmentType.Other:
                break;
            default:
                throw new ArgumentOutOfRangeException();
        }
    }


    private void SwapWeapon()
    {
    
    
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
    
    
            if (MainWeapon == null) return;
            //更换为主武器
            if (carriedWeapon == MainWeapon) return;
            if (carriedWeapon.gameObject.activeInHierarchy)
            {
    
    
                StartWaitingForHolsterEndCoroutine();
                carriedWeapon.GunAnimator.SetTrigger("holster");
            }
            else
            {
    
    
                SetupCarriedWeapon(MainWeapon);
            }
        }
        else if (Input.GetKeyDown(KeyCode.Alpha2))
        {
    
    
            if (SecondaryWeapon == null) return;
            //更换为副武器
            if (carriedWeapon == SecondaryWeapon) return;
            if (carriedWeapon.gameObject.activeInHierarchy)
            {
    
    
                StartWaitingForHolsterEndCoroutine();
                carriedWeapon.GunAnimator.SetTrigger("holster");
            }
            else
            {
    
    
                SetupCarriedWeapon(SecondaryWeapon);
            }
        }
    }


    private void StartWaitingForHolsterEndCoroutine()
    {
    
    
        if (waitingForHolsterEndCoroutine == null)
            waitingForHolsterEndCoroutine = WaitingForHolsterEnd();
        StartCoroutine(waitingForHolsterEndCoroutine);
    }


    private IEnumerator WaitingForHolsterEnd()
    {
    
    
        while (true)
        {
    
    
            AnimatorStateInfo tmp_AnimatorStateInfo = carriedWeapon.GunAnimator.GetCurrentAnimatorStateInfo(0);
            if (tmp_AnimatorStateInfo.IsTag("holster"))
            {
    
    
                if (tmp_AnimatorStateInfo.normalizedTime >= 0.9f)
                {
    
    
                    var tmp_TargetWeapon = carriedWeapon == MainWeapon ? SecondaryWeapon : MainWeapon;
                    SetupCarriedWeapon(tmp_TargetWeapon);
                    waitingForHolsterEndCoroutine = null;
                    yield break;
                }
            }

            yield return null;
        }
    }


    private void SetupCarriedWeapon(Firearms _targetWeapon)
    {
    
    
        if (carriedWeapon)
            carriedWeapon.gameObject.SetActive(false);
        carriedWeapon = _targetWeapon;
        carriedWeapon.gameObject.SetActive(true);
        CharacterControllerMovement.SetupAnimator(carriedWeapon.GunAnimator);
    }

    [PunRPC]
    private void RPC_HoldTrigger()
    {
    
    
        carriedWeapon.HoldTrigger();
    }

    [PunRPC]
    private void RPC_ReleaseTrigger()
    {
    
    
        carriedWeapon.ReleaseTrigger();
    }

    [PunRPC]
    private void RPC_ReloadAmmo()
    {
    
    
        carriedWeapon.ReloadAmmo();
    }
}
}

猜你喜欢

转载自blog.csdn.net/Fancy145/article/details/125055950
今日推荐