Hello & Good evening!
now I have rethought it… and my result looks like you can see on the following screenshot:
One player is able to control the car and the other can control the tower and shoot. But I think the
implementation/logic behind sucks ![]()
My Idea:
I have dragged a car model in the scene (just with a rigidbody, box collider, wheel collider etc.).
And I spawn a player (empty Gameobject with the “CAR1” Script on it.
Is there a better solution or an advice?
Thank you ![]()
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
[System.Serializable]
public class AxleInfo11
{
public WheelCollider leftWheel;
public WheelCollider rightWheel;
public bool motor;
public bool steering;
}
public class CAR1 : NetworkBehaviour
{
public List<AxleInfo11> axleInfos;
public float maxMotorTorque; public float maxSteeringAngle;
private float LerpValue = 2;
private float MinPosDist = 0.5F;
public int playerMODE = 0;
private CAR1 carScript;
GameObject carCRAB;
private Transform towerObject;
private Transform cannon;
private Transform gunTIP;
private Vector3 lastTankpos; private Quaternion lastTankRot;
//Geschützturm
private float lsTowerRotationY; private float LerpTurningTower = 2; private float MinMovementTower = 2F;
private float lsCannonRotZ; private float LerpTurningCannon = 2; private float MinMovmentCannon = 2F;
//Motor-Steering
private float lsTankSteering; private float LerpTankSteering = 0.5F; private float MinAngleSteering = 2F;
private float lsTankMotor; private float LerpTankMotor = 0.5F; private float MinAngleMotor = 2F;
[SyncVar] private Vector3 cTankPos;
[SyncVar] private Quaternion cTankRot;
[SyncVar] public float motorVar;
[SyncVar] public float steeringVar;
[SyncVar] public float towerRotationY;
[SyncVar] public float cannonRotationZ;
private float rotationZ = 0f;
private float sensitivityZ = 2f;
private AudioSource shootSound;
private ParticleSystem particleShootingSmoke;
void Start()
{
//FIND TANK
carCRAB = GameObject.Find("CarLokal");
towerObject = GameObject.Find("Drehturm").transform;
shootSound = towerObject.GetComponent<AudioSource>();
cannon = GameObject.Find("Drehkanone").transform;
gunTIP = GameObject.Find("WEAPONTIP").transform;
particleShootingSmoke = gunTIP.GetChild(0).transform.GetComponent<ParticleSystem>();
carScript = GetComponent<CAR1>();
carScript.axleInfos[0].leftWheel = carCRAB.transform.GetChild(1).transform.GetComponent<WheelCollider>(); ;
carScript.axleInfos[0].rightWheel = carCRAB.transform.GetChild(2).transform.GetComponent<WheelCollider>(); ;
carScript.axleInfos[1].leftWheel = carCRAB.transform.GetChild(3).transform.GetComponent<WheelCollider>(); ;
carScript.axleInfos[1].rightWheel = carCRAB.transform.GetChild(4).transform.GetComponent<WheelCollider>(); ;
//tank won't flip that easy
Rigidbody rb = carCRAB.GetComponent<Rigidbody>();
rb.centerOfMass = new Vector3(0, -0.4F, 0);
playerMODE = GameObject.Find("NETWORKMANAGER").GetComponent<CurrentPos>().playerMODE;
if (playerMODE == 1)
{
rb.isKinematic = true;
}
}
void Update()
{
if(playerMODE==1)
{
if (Input.GetButtonDown("Fire1"))
{
StopCoroutine("Shoot");
StartCoroutine("Shoot");
}
}
}
// example unity
public void ApplyLocalPositionToVisuals(WheelCollider collider)
{
if (collider.transform.childCount == 0)
{
return;
}
Transform visualWheel = collider.transform.GetChild(0);
Vector3 position;
Quaternion rotation;
collider.GetWorldPose(out position, out rotation);
visualWheel.transform.position = position;
visualWheel.transform.rotation = rotation;
}
private void ChangeAxisValues(float steering1, float motor1)
{
foreach (AxleInfo11 axleInfo in axleInfos)
{
if (axleInfo.steering)
{
axleInfo.leftWheel.steerAngle = steering1;
axleInfo.rightWheel.steerAngle = steering1;
}
if (axleInfo.motor)
{
axleInfo.leftWheel.motorTorque = motor1;
axleInfo.rightWheel.motorTorque = motor1;
}
ApplyLocalPositionToVisuals(axleInfo.leftWheel);
ApplyLocalPositionToVisuals(axleInfo.rightWheel);
}
}
public void FixedUpdate()
{
//MODE == DRIVER
if (playerMODE == 0)
{
float motor = maxMotorTorque * Input.GetAxis("Vertical");
float steering = maxSteeringAngle * Input.GetAxis("Horizontal");
ChangeAxisValues(steering, motor);
Vector3 currPos = carCRAB.transform.position;
ChangeCarPosition(currPos);
Quaternion currRot = carCRAB.transform.rotation;
ChangeCarRotation(currRot);
if (isOverThreshold(lastTankpos, currPos, MinPosDist))
{
CmdSendPosition(currPos);
lastTankpos = currPos;
CmdSendRotation(currRot);
lastTankRot = currRot;
CmdSendMotor(motor);
lsTankMotor = motor;
}
//TOWER
InterpolateTurretY();
InterpolateKanoneZ();
if (isOverThresholdFloat(lsTankSteering, steering, MinAngleSteering))
{
CmdSendSteering(steering);
lsTankSteering = steering;
}
}
else //MODE == SHOOTER
{
Interpolate();
InterpolateRot();
ChangeAxisValues(InterpolateSteering(), motorVar);
//ROTATION WHOLE TOWER
towerObject.transform.Rotate(0.0f, Input.GetAxis("Horizontal") * 2, 0.0f);
if (isOverThresholdTurret(lsTowerRotationY, towerObject.transform.localRotation.y, MinMovementTower))
{
CmdSendTowerY(towerObject.transform.localEulerAngles.y);
lsTowerRotationY = towerObject.transform.localEulerAngles.y;
}
//TOTATE CANNON
rotationZ += Input.GetAxis("Vertical") * sensitivityZ;
rotationZ = Mathf.Clamp(rotationZ, -20, 90);
cannon.transform.localEulerAngles = new Vector3(cannon.transform.localEulerAngles.x, cannon.transform.localEulerAngles.y, -rotationZ);
if (isOverThresholdDrehKanone(lsCannonRotZ, cannon.transform.localEulerAngles.z, MinMovmentCannon))
{
CmdSendDrehKanoneZ(cannon.transform.localEulerAngles.z);
lsCannonRotZ = cannon.transform.localEulerAngles.z;
}
}
}
//CAR POSITION
[Command]
private void CmdSendPosition(Vector3 pos)
{
cTankPos = pos;
}
[Client]
private void ChangeCarPosition(Vector3 pos)
{
carCRAB.transform.position = pos;
}
[Command]
private void CmdSendMotor(float motor)
{
motorVar = motor;
}
[Command]
private void CmdSendSteering(float steering)
{
steeringVar = steering;
}
//CAR ROTATION
[Command]
private void CmdSendRotation(Quaternion rot)
{
cTankRot = rot;
}
[Client]
private void ChangeCarRotation(Quaternion rot)
{
carCRAB.transform.rotation = rot;
}
//TOWER
[Command]
private void CmdSendTowerY(float rotY)
{
lsTowerRotationY = rotY;
}
[Command]
private void CmdSendDrehKanoneZ(float rotZ)
{
lsCannonRotZ = rotZ;
}
//INTERPOLATION STUFF --> simplify later on
private void Interpolate()
{
Vector3 pos = Vector3.Lerp(carCRAB.transform.position, cTankPos, Time.deltaTime * LerpValue);
carCRAB.transform.position = pos;
}
private void InterpolateRot()
{
Quaternion rot = Quaternion.Lerp(carCRAB.transform.rotation, cTankRot, Time.deltaTime * LerpValue);
carCRAB.transform.rotation = rot;
}
private void InterpolateTurretY()
{
towerObject.transform.localEulerAngles = new Vector3(towerObject.transform.localEulerAngles.x, Mathf.Lerp(towerObject.transform.localEulerAngles.y, lsTowerRotationY, LerpTurningTower), towerObject.transform.localEulerAngles.z);
}
private void InterpolateKanoneZ()
{
cannon.transform.localEulerAngles = new Vector3(cannon.transform.localEulerAngles.x, cannon.transform.localEulerAngles.y, Mathf.Lerp(cannon.transform.localEulerAngles.y, lsCannonRotZ, LerpTurningCannon));
}
private float InterpolateSteering()
{
return Mathf.Lerp(lsTankSteering, steeringVar, LerpTankSteering);
}
private float InterpolateMotor()
{
return Mathf.Lerp(lsTankMotor, motorVar, LerpTankMotor);
}
private bool isOverThreshold(Vector3 old, Vector3 pos, float threshold)
{
return Vector3.Distance(old, pos) > threshold;
}
private bool isOverThresholdTurret(float old, float pos, float angleThreshold)
{
return (old - pos) > angleThreshold || (old - pos) < angleThreshold;
}
private bool isOverThresholdDrehKanone(float old, float pos, float angleThreshold)
{
return (old - pos) > angleThreshold || (old - pos) < angleThreshold;
}
private bool isOverThresholdFloat(float old, float pos, float angleThreshold)
{
return (old - pos) > angleThreshold || (old - pos) < angleThreshold;
}
IEnumerator Shoot()
{
while (Input.GetButton("Fire1"))
{
CmdShoot();
shootSound.Stop();
shootSound.Play();
particleShootingSmoke.Play();
Vector3 fwd = gunTIP.transform.TransformDirection(Vector3.forward);
Debug.DrawRay(gunTIP.transform.position, fwd * 50, Color.green);
RaycastHit hit;
if (Physics.Raycast(gunTIP.transform.position, fwd, out hit, 100))
{
Debug.DrawLine(gunTIP.transform.position, hit.point, Color.red);
if (hit.transform.tag == "ENEMY")
{
Debug.Log("TEST");
}
}
particleShootingSmoke.Stop();
yield return new WaitForSeconds(0.1F);
}
}
[Command]
public void CmdShoot()
{
shootSound.Stop();
shootSound.Play();
particleShootingSmoke.Play();
Vector3 fwd = gunTIP.transform.TransformDirection(Vector3.forward);
Debug.DrawRay(gunTIP.transform.position, fwd * 50, Color.green);
RaycastHit hit;
if (Physics.Raycast(gunTIP.transform.position, fwd, out hit, 100))
{
Debug.DrawLine(gunTIP.transform.position, hit.point, Color.red);
if (hit.transform.tag == "ENEMY")
{
Debug.Log("TEST");
}
}
particleShootingSmoke.Stop();
}
}
OLD THOUGHTS
firstly I’ve found similar threads but unfortunately I can’t really solve my problem ![]()
I’ve tried several things but I’m… stuck.
Idea:
I want the user to join a room and then walk to different vehicles and control them. Further more I want that player1 controls the car movement and player2 the rotation of the turret (or is able to control the radio etc…).
Simplification:
Empty Gameobject Player spawns:
currentmode =0 → Player can control the car
currentmode =1 → Player can control the turret
Problem.
I’m not sure about the logic behind the scenario.
-
My first thought was to create 1 car in my scene add a network identity, check Local Player Authority, add a network transform to that car. And when the game starts each player can control this 1 car.
-
Or do I instantiate for all player in that car 1 car object and disable the visibility and then sync.
Player 1 → syncs turret rotation/ receives car position
Player 2 → syncs car movement/ receives turret rotation
Hmm appreciate some hints/help ![]()
Short:
I want two ore more player to control different car gadgets.
And for those who aren’t confused yet…: ![]()
My plan:
- Empty Gameobject (Network Identity → local player authority checked) assigned to the Network Manager Script
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class PlayerController : NetworkBehaviour {
GameObject car;
int currentmode = 0;
public GUISkin guistyle;
private CarController carcontroller;
private CarShooter carShooter;
void Start()
{
car = GameObject.Find("CarLokal");
carcontroller = car.GetComponent<CarController>();
carShooter = car.GetComponent<CarShooter>();
}
void OnGUI()
{
if(!isLocalPlayer || isServer)
{
return;
}
GUI.skin = guistyle;
GUI.color = Color.red;
GUILayout.BeginArea(new Rect(Screen.width / 2 - 200, Screen.height - 100, 400, 400));
if (GUILayout.Button("Mode1"))
{
currentmode = 0;
}
if (GUILayout.Button("Mode2"))
{
currentmode = 1;
}
GUILayout.Label("MODE: " + currentmode);
GUILayout.EndArea();
}
void Update () {
if (!isLocalPlayer)
{
return;
}
if(currentmode==0)
{
if(carcontroller !=null)
{
carcontroller.GiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// carcontroller.RpcGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// carcontroller.CmdGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
}
}
else
{
if(carShooter !=null)
{
carShooter.GiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// carShooter.RpcGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// carShooter.CmdGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
}
}
}
}
Car placed in the scene (Network Identity-> Local Player Authority checked + Car Shooter (Script) + Network Transform?!)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
[System.Serializable]
public class AxleInfo2
{
public WheelCollider leftWheel;
public WheelCollider rightWheel;
public bool motor;
public bool steering;
}
public class CarController : NetworkBehaviour {
public List<AxleInfo2> axleInfos;
public float maxMotorTorque;
public float maxSteeringAngle;
private PlayerCamera playerCamera;
void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.centerOfMass = new Vector3(0, -0.4F, 0);
}
// finds the corresponding visual wheel
// correctly applies the transform
public void ApplyLocalPositionToVisuals(WheelCollider collider)
{
if (collider.transform.childCount == 0)
{
return;
}
Transform visualWheel = collider.transform.GetChild(0);
Vector3 position;
Quaternion rotation;
collider.GetWorldPose(out position, out rotation);
visualWheel.transform.position = position;
visualWheel.transform.rotation = rotation;
}
[SyncVar]
public float currentVert=0;
[SyncVar]
public float currentHori=0;
//Now let's start the confusion party :)
[Command]
public void CmdGiveVal(float currentVert, float currentHori)
{
this.currentVert = currentVert;
this.currentHori = currentHori;
}
public void GiveVal(float currentVert, float currentHori)
{
this.currentVert = currentVert;
this.currentHori = currentHori;
}
[ClientRpc]
public void RpcGiveVal(float currentVert, float currentHori)
{
this.currentVert = currentVert;
this.currentHori = currentHori;
}
public void FixedUpdate()
{
// if (!isServer)
// {
// RpcSpreadVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// }
// if (isLocalPlayer)
// {
// RpcGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// }
// if(!isLocalPlayer)
// {
// return;
// }
// GiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
float motor = maxMotorTorque * currentVert;
float steering = maxSteeringAngle * currentHori;
foreach (AxleInfo2 axleInfo in axleInfos)
{
if (axleInfo.steering)
{
axleInfo.leftWheel.steerAngle = steering;
axleInfo.rightWheel.steerAngle = steering;
}
if (axleInfo.motor)
{
axleInfo.leftWheel.motorTorque = motor;
axleInfo.rightWheel.motorTorque = motor;
}
ApplyLocalPositionToVisuals(axleInfo.leftWheel);
ApplyLocalPositionToVisuals(axleInfo.rightWheel);
}
}
}
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class CarShooter : NetworkBehaviour {
public Transform tower;
public Transform towerBarrel;
[SyncVar]
public float currentVert = 0;
[SyncVar]
public float currentHori = 0;
[Command]
public void CmdGiveVal(float currentVert, float currentHori)
{
this.currentVert = currentVert;
this.currentHori = currentHori;
}
// Use this for initialization
void Start () {
}
float speed = 4;
[ClientRpc]
public void RpcGiveVal(float currentVert, float currentHori)
{
this.currentVert = currentVert;
this.currentHori = currentHori;
}
public void GiveVal(float currentVert, float currentHori)
{
this.currentVert = currentVert;
this.currentHori = currentHori;
}
private float rotationZ = 0f;
private float sensitivityZ = 2f;
// Update is called once per frame
void Update () {
// GiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// if(isLocalPlayer)
// {
// RpcGiveVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// }
// if (!isServer)
// {
// RpcSpreadVal(Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"));
// }
tower.transform.Rotate(0.0f, currentHori * speed, 0.0f);
// towerBarrel.transform.Rotate(0.0f, -Input.GetAxis("V") * speed, 0.0f);
// towerBarrel.transform.Rotate(0, Input.GetAxis("Vertical") * speed * Time.deltaTime, 0);
//The function is Mathf.Clamp(value, min, max)
rotationZ += currentVert * sensitivityZ;
rotationZ = Mathf.Clamp(rotationZ, -20, 90);
towerBarrel.transform.localEulerAngles = new Vector3(towerBarrel.transform.localEulerAngles.x, towerBarrel.transform.localEulerAngles.y, -rotationZ);
/* if (Input.GetKey(KeyCode.A))
{
transform.Rotate(Vector3.up * speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.D))
transform.Rotate(-Vector3.up * speed * Time.deltaTime);
*/
}
}
Regards Leo

