Многопользовательский сценарий появления пули Unity
Я работаю над многопользовательским шутером, и до сих пор у меня работали сетевые системы перемещения и захвата оружия. Скрипт оружия работает в одиночной игре, и теперь я должен перенести его в многопользовательский режим. Вот весь код, связанный с проблемой:
PlayerController.cs:
using UnityEngine;
using System.Collections;
using System;
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float Speed;
public bool OnGamepad = false;
private bool OnPrimary = true;
private Vector3 MoveData = Vector3.zero;
private Rigidbody PlayerRB;
public Camera PlayerCam;
public Transform gunOrigin;
public CombatItem Primary;
public CombatItem Secondary;
void Start()
{
PlayerRB = GetComponent<Rigidbody>();
PlayerCam = Instantiate(PlayerCam, transform.position, transform.rotation) as Camera;
PlayerCam.GetComponent<CameraControl>().target = transform;
PlayerCam.transform.parent = transform.parent;
}
void FixedUpdate ()
{
gameObject.SetActive(true);
checkConrolMethod();
Move();
if (OnPrimary && Primary != null) Action1(Primary);
else if(!OnPrimary && Secondary != null) Action1(Secondary);
if (OnGamepad)
{
GamepadRotate();
}
else
{
Rotate();
}
}
void Move()
{
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
MoveData.Set(x, 0f, z);
MoveData = MoveData.normalized * Speed;
PlayerRB.MovePosition(PlayerRB.position + MoveData * Time.deltaTime);
}
void Rotate()
{
Ray camRay = PlayerCam.ScreenPointToRay(Input.mousePosition);
Plane floor = new Plane(Vector3.up, Vector3.zero);
float rayL;
if (floor.Raycast(camRay, out rayL))
{
Vector3 lookPoint = camRay.GetPoint(rayL);
transform.LookAt(new Vector3(lookPoint.x, transform.position.y, lookPoint.z));
}
}
void GamepadRotate()
{
Vector3 direction = Vector3.right * Input.GetAxisRaw("GPLookHorizontal")
+ Vector3.forward * -Input.GetAxisRaw("GPLookVertical");
if(direction.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(direction, Vector3.up);
}
}
void checkConrolMethod()
{
if (Input.GetJoystickNames().Length != 0)
OnGamepad = true;
if (Input.GetAxisRaw("Fire") != 0
|| Input.GetAxisRaw("Mouse X") != 0
|| Input.GetAxisRaw("Mouse X") != 0)
OnGamepad = false;
}
void OnCollisionEnter(Collision c)
{
if(c.gameObject.tag == "Bullet")
{
transform.position = new Vector3(0, transform.position.y, 0);
}
else if(c.gameObject.tag == "CombatItem")
{
PickUp(c.gameObject);
}
}
void PickUp(GameObject g)
{
g.transform.parent = transform;
g.transform.position = gunOrigin.transform.position;
g.transform.rotation = gunOrigin.transform.rotation;
CombatItem c = g.GetComponent<CombatItem>();
c.equiped = true;
if (OnPrimary) Primary = c;
else Secondary = c;
}
void Action1(CombatItem c)
{
if (Input.GetAxisRaw("Fire") != 0 || Input.GetAxisRaw("GPFire") == -1) c.Action1(true);
else c.Action1(false);
}
void OnDestroy()
{
PlayerCam.GetComponent<CameraControl>().enabled = false;
}
}
CombatItem.cs:
using UnityEngine;
using System.Collections;
public class CombatItem : MonoBehaviour
{
public bool equiped = false;
public virtual void Action1(bool on){}
public virtual void Action2(bool on){}
}
GunContoller.cs:
using UnityEngine;
using System.Collections;
using System;
public class GunController : CombatItem
{
[SerializeField]
Transform Origin;
[SerializeField]
Bullet b;
float ROFCountDown;
float TimeBetweenShots;
public float RateOfFire;
bool SingleShot;
bool IsFiring;
void Start()
{
TimeBetweenShots = 60 / RateOfFire;
}
void Update()
{
Fire();
}
public void Fire()
{
ROFCountDown -= Time.deltaTime;
if (IsFiring)
{
if (ROFCountDown <= 0)
{
ROFCountDown = TimeBetweenShots;
Bullet newBullet = Instantiate(b, Origin.position, Origin.rotation) as Bullet;
}
}
}
public override void Action1(bool on)
{
IsFiring = on;
}
public override void Action2(bool on)
{
}
}
и Bullet.cs:
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour
{
public float Speed;
public float Range;
Vector3 initPosition;
void Start()
{
initPosition = transform.position;
}
void FixedUpdate()
{
transform.Translate(Vector3.forward * Speed * Time.deltaTime);
if (Vector3.Distance(transform.position, initPosition) > Range)
{
Destroy(this.gameObject);
}
}
}
Итак, быстрое подведение итогов того, что происходит. CombatItem
это класс, который предоставляет сценарию игрока возможность взаимодействовать с несколькими видами... хороших боевых предметов - оружия, гранат, оружия ближнего боя, флага CTF, если я доберусь до этого, и т. д. Оттуда каждый тип боевого предмета наследует этот класс и использует Action1()
а также Action2()
чтобы вызвать функциональность CombatItem
, который реализован в каждом CombatItem
учебный класс.
Здесь проблема. Чтобы я мог вызвать пулю, мне нужно отправить функцию [Command], содержащую NetworkServer.Spawn(bulletGameObject)
(например). Проблема в том, что я не могу сделать это в GunController
или PlayerController
сценарии, так как они есть и должны быть MonoBehaviour
(этот код должен использоваться и в одиночной игре). Мне нужен способ порождения пули "вне" этого кода. Надеюсь, я объяснил это достаточно правильно.......
Все префабы, связанные с этими сценариями, были правильно настроены с использованием сетевых идентификаторов и преобразований и были добавлены в список зарегистрированных префабов. Я понимаю, что для появления пули мне нужно NetworkServer.Spawn()
, который требует gameObject с полномочиями клиента для правильного появления. Я просто не могу понять, как получить доступ к новому экземпляру маркера из вторичного скрипта (возможно, привязанного к префабу плеера).
РЕДАКТИРОВАТЬ: Это что-то близко к тому, что мне нужно, имейте в виду, что это в основном своего рода псевдокод
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class NetGun : NetworkBehaviour {
[SerializeField]
GunController GC;
void Start ()
{
}
void Update ()
{
if(GC.equiped)
{
this.GetComponent<NetworkIdentity>().AssignClientAuthority(connectionToClient);
}
CmdSpawnBullet();
}
[Command]
void CmdSpawnBullet()
{
if (GC.Fire() != null)
{
NetworkServer.Spawn(GC.Fire());
}
}
}
Как я уже сказал, этот код не функционален, он должен объяснить ситуацию немного лучше. Я хочу, чтобы пистолет мог порождать пулю в NetworkBehaviour
сценарий отдельно от GunController
, Я так хочу, потому что будут боевые предметы, которые не порождают снаряды...