- Home /
NEED p2 car script
hello I am trying to make a racing game for two players (as 1 player is no fun) I just need to make it so that the controls for each player is different as now WASD are the controls for p1 and p2. I have tried to copy the car controller asset that comes with unity but I've had no luck (I am also trying to use only C# so C# would be helpful thanks) what I have so far:
using System; using UnityEngine;
namespace UnityStandardAssets.player2 { internal enum CarDriveType { FrontWheelDrive, RearWheelDrive, FourWheelDrive }
internal enum SpeedType
{
MPH,
KPH
}
public class player2carcontroller : MonoBehaviour
{
[SerializeField]
private CarDriveType m_CarDriveType = CarDriveType.FourWheelDrive;
[SerializeField]
private WheelCollider[] m_WheelColliders = new WheelCollider[4];
[SerializeField]
private GameObject[] m_WheelMeshes = new GameObject[4];
[SerializeField]
private player2wheel[] m_WheelEffects = new player2wheel[4];
[SerializeField]
private Vector3 m_CentreOfMassOffset;
[SerializeField]
private float m_MaximumSteerAngle;
[Range(0, 1)]
[SerializeField]
private float m_SteerHelper; // 0 is raw physics , 1 the car will grip in the direction it is facing
[Range(0, 1)]
[SerializeField]
private float m_TractionControl; // 0 is no traction control, 1 is full interference
[SerializeField]
private float m_FullTorqueOverAllWheels;
[SerializeField]
private float m_ReverseTorque;
[SerializeField]
private float m_MaxHandbrakeTorque;
[SerializeField]
private float m_Downforce = 100f;
[SerializeField]
private SpeedType m_SpeedType;
[SerializeField]
private float m_Topspeed = 200;
[SerializeField]
private static int NoOfGears = 5;
[SerializeField]
private float m_RevRangeBoundary = 1f;
[SerializeField]
private float m_SlipLimit;
[SerializeField]
private float m_BrakeTorque;
private Quaternion[] m_WheelMeshLocalRotations;
private Vector3 m_Prevpos, m_Pos;
private float m_SteerAngle;
private int m_GearNum;
private float m_GearFactor;
private float m_OldRotation;
private float m_CurrentTorque;
private Rigidbody m_Rigidbody;
private const float k_ReversingThreshold = 0.01f;
public bool Skidding { get; private set; }
public float BrakeInput { get; private set; }
public float CurrentSteerAngle { get { return m_SteerAngle; } }
public float CurrentSpeed { get { return m_Rigidbody.velocity.magnitude * 2.23693629f; } }
public float MaxSpeed { get { return m_Topspeed; } }
public float Revs { get; private set; }
public float AccelInput { get; private set; }
// Use this for initialization
private void Start()
{
m_WheelMeshLocalRotations = new Quaternion[4];
for (int i = 0; i < 4; i++)
{
m_WheelMeshLocalRotations[i] = m_WheelMeshes[i].transform.localRotation;
}
m_WheelColliders[0].attachedRigidbody.centerOfMass = m_CentreOfMassOffset;
m_MaxHandbrakeTorque = float.MaxValue;
m_Rigidbody = GetComponent<Rigidbody>();
m_CurrentTorque = m_FullTorqueOverAllWheels - (m_TractionControl * m_FullTorqueOverAllWheels);
}
private void GearChanging()
{
float f = Mathf.Abs(CurrentSpeed / MaxSpeed);
float upgearlimit = (1 / (float)NoOfGears) * (m_GearNum + 1);
float downgearlimit = (1 / (float)NoOfGears) * m_GearNum;
if (m_GearNum > 0 && f < downgearlimit)
{
m_GearNum--;
}
if (f > upgearlimit && (m_GearNum < (NoOfGears - 1)))
{
m_GearNum++;
}
}
// simple function to add a curved bias towards 1 for a value in the 0-1 range
private static float CurveFactor(float factor)
{
return 1 - (1 - factor) * (1 - factor);
}
// unclamped version of Lerp, to allow value to exceed the from-to range
private static float ULerp(float from, float to, float value)
{
return (1.0f - value) * from + value * to;
}
private void CalculateGearFactor()
{
float f = (1 / (float)NoOfGears);
// gear factor is a normalised representation of the current speed within the current gear's range of speeds.
// We smooth towards the 'target' gear factor, so that revs don't instantly snap up or down when changing gear.
var targetGearFactor = Mathf.InverseLerp(f * m_GearNum, f * (m_GearNum + 1), Mathf.Abs(CurrentSpeed / MaxSpeed));
m_GearFactor = Mathf.Lerp(m_GearFactor, targetGearFactor, Time.deltaTime * 5f);
}
private void CalculateRevs()
{
// calculate engine revs (for display / sound)
// (this is done in retrospect - revs are not used in force/power calculations)
CalculateGearFactor();
var gearNumFactor = m_GearNum / (float)NoOfGears;
var revsRangeMin = ULerp(0f, m_RevRangeBoundary, CurveFactor(gearNumFactor));
var revsRangeMax = ULerp(m_RevRangeBoundary, 1f, gearNumFactor);
Revs = ULerp(revsRangeMin, revsRangeMax, m_GearFactor);
}
public void Move(float steering, float accel, float footbrake, float handbrake)
{
for (int i = 0; i < 4; i++)
{
Quaternion quat;
Vector3 position;
m_WheelColliders[i].GetWorldPose(out position, out quat);
m_WheelMeshes[i].transform.position = position;
m_WheelMeshes[i].transform.rotation = quat;
}
//clamp input values
steering = Mathf.Clamp(steering, -1, 1);
AccelInput = accel = Mathf.Clamp(accel, 0, 1);
BrakeInput = footbrake = -1 * Mathf.Clamp(footbrake, -1, 0);
handbrake = Mathf.Clamp(handbrake, 0, 1);
//Set the steer on the front wheels.
//Assuming that wheels 0 and 1 are the front wheels.
m_SteerAngle = steering * m_MaximumSteerAngle;
m_WheelColliders[0].steerAngle = m_SteerAngle;
m_WheelColliders[1].steerAngle = m_SteerAngle;
SteerHelper();
ApplyDrive(accel, footbrake);
CapSpeed();
//Set the handbrake.
//Assuming that wheels 2 and 3 are the rear wheels.
if (handbrake > 0f)
{
var hbTorque = handbrake * m_MaxHandbrakeTorque;
m_WheelColliders[2].brakeTorque = hbTorque;
m_WheelColliders[3].brakeTorque = hbTorque;
}
CalculateRevs();
GearChanging();
AddDownForce();
CheckForWheelSpin();
TractionControl();
}
private void CapSpeed()
{
float speed = m_Rigidbody.velocity.magnitude;
switch (m_SpeedType)
{
case SpeedType.MPH:
speed *= 2.23693629f;
if (speed > m_Topspeed)
m_Rigidbody.velocity = (m_Topspeed / 2.23693629f) * m_Rigidbody.velocity.normalized;
break;
case SpeedType.KPH:
speed *= 3.6f;
if (speed > m_Topspeed)
m_Rigidbody.velocity = (m_Topspeed / 3.6f) * m_Rigidbody.velocity.normalized;
break;
}
}
private void ApplyDrive(float accel, float footbrake)
{
float thrustTorque;
switch (m_CarDriveType)
{
case CarDriveType.FourWheelDrive:
thrustTorque = accel * (m_CurrentTorque / 4f);
for (int i = 0; i < 4; i++)
{
m_WheelColliders[i].motorTorque = thrustTorque;
}
break;
case CarDriveType.FrontWheelDrive:
thrustTorque = accel * (m_CurrentTorque / 2f);
m_WheelColliders[0].motorTorque = m_WheelColliders[1].motorTorque = thrustTorque;
break;
case CarDriveType.RearWheelDrive:
thrustTorque = accel * (m_CurrentTorque / 2f);
m_WheelColliders[2].motorTorque = m_WheelColliders[3].motorTorque = thrustTorque;
break;
}
for (int i = 0; i < 4; i++)
{
if (CurrentSpeed > 5 && Vector3.Angle(transform.forward, m_Rigidbody.velocity) < 50f)
{
m_WheelColliders[i].brakeTorque = m_BrakeTorque * footbrake;
}
else if (footbrake > 0)
{
m_WheelColliders[i].brakeTorque = 0f;
m_WheelColliders[i].motorTorque = -m_ReverseTorque * footbrake;
}
}
}
private void SteerHelper()
{
for (int i = 0; i < 4; i++)
{
WheelHit wheelhit;
m_WheelColliders[i].GetGroundHit(out wheelhit);
if (wheelhit.normal == Vector3.zero)
return; // wheels arent on the ground so dont realign the rigidbody velocity
}
// this if is needed to avoid gimbal lock problems that will make the car suddenly shift direction
if (Mathf.Abs(m_OldRotation - transform.eulerAngles.y) < 10f)
{
var turnadjust = (transform.eulerAngles.y - m_OldRotation) * m_SteerHelper;
Quaternion velRotation = Quaternion.AngleAxis(turnadjust, Vector3.up);
m_Rigidbody.velocity = velRotation * m_Rigidbody.velocity;
}
m_OldRotation = transform.eulerAngles.y;
}
// this is used to add more grip in relation to speed
private void AddDownForce()
{
m_WheelColliders[0].attachedRigidbody.AddForce(-transform.up * m_Downforce *
m_WheelColliders[0].attachedRigidbody.velocity.magnitude);
}
// checks if the wheels are spinning and is so does three things
// 1) emits particles
// 2) plays tiure skidding sounds
// 3) leaves skidmarks on the ground
// these effects are controlled through the WheelEffects class
private void CheckForWheelSpin()
{
// loop through all wheels
for (int i = 0; i < 4; i++)
{
WheelHit wheelHit;
m_WheelColliders[i].GetGroundHit(out wheelHit);
// is the tire slipping above the given threshhold
if (Mathf.Abs(wheelHit.forwardSlip) >= m_SlipLimit || Mathf.Abs(wheelHit.sidewaysSlip) >= m_SlipLimit)
{
m_WheelEffects[i].EmitTyreSmoke();
// avoiding all four tires screeching at the same time
// if they do it can lead to some strange audio artefacts
if (!AnySkidSoundPlaying())
{
m_WheelEffects[i].PlayAudio();
}
continue;
}
// if it wasnt slipping stop all the audio
if (m_WheelEffects[i].PlayingAudio)
{
m_WheelEffects[i].StopAudio();
}
// end the trail generation
m_WheelEffects[i].EndSkidTrail();
}
}
// crude traction control that reduces the power to wheel if the car is wheel spinning too much
private void TractionControl()
{
WheelHit wheelHit;
switch (m_CarDriveType)
{
case CarDriveType.FourWheelDrive:
// loop through all wheels
for (int i = 0; i < 4; i++)
{
m_WheelColliders[i].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
}
break;
case CarDriveType.RearWheelDrive:
m_WheelColliders[2].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
m_WheelColliders[3].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
break;
case CarDriveType.FrontWheelDrive:
m_WheelColliders[0].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
m_WheelColliders[1].GetGroundHit(out wheelHit);
AdjustTorque(wheelHit.forwardSlip);
break;
}
}
private void AdjustTorque(float forwardSlip)
{
if (forwardSlip >= m_SlipLimit && m_CurrentTorque >= 0)
{
m_CurrentTorque -= 10 * m_TractionControl;
}
else
{
m_CurrentTorque += 10 * m_TractionControl;
if (m_CurrentTorque > m_FullTorqueOverAllWheels)
{
m_CurrentTorque = m_FullTorqueOverAllWheels;
}
}
}
private bool AnySkidSoundPlaying()
{
for (int i = 0; i < 4; i++)
{
if (m_WheelEffects[i].PlayingAudio)
{
return true;
}
}
return false;
}
}
}
using System; using UnityEngine; using UnityStandardAssets.CrossPlatformInput;
namespace UnityStandardAssets.player2 { [RequireComponent(typeof(player2carcontroller))] public class player2 : MonoBehaviour { private player2carcontroller m_Car; // the car controller we want to use
private void Awake()
{
// get the car controller
m_Car = GetComponent<player2carcontroller>();
}
private void FixedUpdate()
{
// pass the input to the car!
float h = CrossPlatformInputManager.GetAxis("Horizontal2");
float v = CrossPlatformInputManager.GetAxis("Vertical2");
if !MOBILE_INPUT
float handbrake = CrossPlatformInputManager.GetAxis("Jump2");
m_Car.Move(h, v, v, handbrake);
else
m_Car.Move(h, v, v, 0f);
endif
}
}
}
using System; using UnityEngine; using Random = UnityEngine.Random;
namespace UnityStandardAssets.player2 { [RequireComponent(typeof(player2carcontroller))] public class player2audio : MonoBehaviour { // This script reads some of the car's current properties and plays sounds accordingly. // The engine sound can be a simple single clip which is looped and pitched, or it // can be a crossfaded blend of four clips which represent the timbre of the engine // at different RPM and Throttle state.
// the engine clips should all be a steady pitch, not rising or falling.
// when using four channel engine crossfading, the four clips should be:
// lowAccelClip : The engine at low revs, with throttle open (i.e. begining acceleration at very low speed)
// highAccelClip : Thenengine at high revs, with throttle open (i.e. accelerating, but almost at max speed)
// lowDecelClip : The engine at low revs, with throttle at minimum (i.e. idling or engine-braking at very low speed)
// highDecelClip : Thenengine at high revs, with throttle at minimum (i.e. engine-braking at very high speed)
// For proper crossfading, the clips pitches should all match, with an octave offset between low and high.
public enum EngineAudioOptions // Options for the engine audio
{
Simple, // Simple style audio
FourChannel // four Channel audio
}
public EngineAudioOptions engineSoundStyle = EngineAudioOptions.FourChannel;// Set the default audio options to be four channel
public AudioClip lowAccelClip; // Audio clip for low acceleration
public AudioClip lowDecelClip; // Audio clip for low deceleration
public AudioClip highAccelClip; // Audio clip for high acceleration
public AudioClip highDecelClip; // Audio clip for high deceleration
public float pitchMultiplier = 1f; // Used for altering the pitch of audio clips
public float lowPitchMin = 1f; // The lowest possible pitch for the low sounds
public float lowPitchMax = 6f; // The highest possible pitch for the low sounds
public float highPitchMultiplier = 0.25f; // Used for altering the pitch of high sounds
public float maxRolloffDistance = 500; // The maximum distance where rollof starts to take place
public float dopplerLevel = 1; // The mount of doppler effect used in the audio
public bool useDoppler = true; // Toggle for using doppler
private AudioSource m_LowAccel; // Source for the low acceleration sounds
private AudioSource m_LowDecel; // Source for the low deceleration sounds
private AudioSource m_HighAccel; // Source for the high acceleration sounds
private AudioSource m_HighDecel; // Source for the high deceleration sounds
private bool m_StartedSound; // flag for knowing if we have started sounds
private player2carcontroller m_CarController; // Reference to car we are controlling
private void StartSound()
{
// get the carcontroller ( this will not be null as we have require component)
m_CarController = GetComponent<player2carcontroller>();
// setup the simple audio source
m_HighAccel = SetUpEngineAudioSource(highAccelClip);
// if we have four channel audio setup the four audio sources
if (engineSoundStyle == EngineAudioOptions.FourChannel)
{
m_LowAccel = SetUpEngineAudioSource(lowAccelClip);
m_LowDecel = SetUpEngineAudioSource(lowDecelClip);
m_HighDecel = SetUpEngineAudioSource(highDecelClip);
}
// flag that we have started the sounds playing
m_StartedSound = true;
}
private void StopSound()
{
//Destroy all audio sources on this object:
foreach (var source in GetComponents<AudioSource>())
{
Destroy(source);
}
m_StartedSound = false;
}
// Update is called once per frame
private void Update()
{
// get the distance to main camera
float camDist = (Camera.main.transform.position - transform.position).sqrMagnitude;
// stop sound if the object is beyond the maximum roll off distance
if (m_StartedSound && camDist > maxRolloffDistance * maxRolloffDistance)
{
StopSound();
}
// start the sound if not playing and it is nearer than the maximum distance
if (!m_StartedSound && camDist < maxRolloffDistance * maxRolloffDistance)
{
StartSound();
}
if (m_StartedSound)
{
// The pitch is interpolated between the min and max values, according to the car's revs.
float pitch = ULerp(lowPitchMin, lowPitchMax, m_CarController.Revs);
// clamp to minimum pitch (note, not clamped to max for high revs while burning out)
pitch = Mathf.Min(lowPitchMax, pitch);
if (engineSoundStyle == EngineAudioOptions.Simple)
{
// for 1 channel engine sound, it's oh so simple:
m_HighAccel.pitch = pitch * pitchMultiplier * highPitchMultiplier;
m_HighAccel.dopplerLevel = useDoppler ? dopplerLevel : 0;
m_HighAccel.volume = 1;
}
else
{
// for 4 channel engine sound, it's a little more complex:
// adjust the pitches based on the multipliers
m_LowAccel.pitch = pitch * pitchMultiplier;
m_LowDecel.pitch = pitch * pitchMultiplier;
m_HighAccel.pitch = pitch * highPitchMultiplier * pitchMultiplier;
m_HighDecel.pitch = pitch * highPitchMultiplier * pitchMultiplier;
// get values for fading the sounds based on the acceleration
float accFade = Mathf.Abs(m_CarController.AccelInput);
float decFade = 1 - accFade;
// get the high fade value based on the cars revs
float highFade = Mathf.InverseLerp(0.2f, 0.8f, m_CarController.Revs);
float lowFade = 1 - highFade;
// adjust the values to be more realistic
highFade = 1 - ((1 - highFade) * (1 - highFade));
lowFade = 1 - ((1 - lowFade) * (1 - lowFade));
accFade = 1 - ((1 - accFade) * (1 - accFade));
decFade = 1 - ((1 - decFade) * (1 - decFade));
// adjust the source volumes based on the fade values
m_LowAccel.volume = lowFade * accFade;
m_LowDecel.volume = lowFade * decFade;
m_HighAccel.volume = highFade * accFade;
m_HighDecel.volume = highFade * decFade;
// adjust the doppler levels
m_HighAccel.dopplerLevel = useDoppler ? dopplerLevel : 0;
m_LowAccel.dopplerLevel = useDoppler ? dopplerLevel : 0;
m_HighDecel.dopplerLevel = useDoppler ? dopplerLevel : 0;
m_LowDecel.dopplerLevel = useDoppler ? dopplerLevel : 0;
}
}
}
// sets up and adds new audio source to the gane object
private AudioSource SetUpEngineAudioSource(AudioClip clip)
{
// create the new audio source component on the game object and set up its properties
AudioSource source = gameObject.AddComponent<AudioSource>();
source.clip = clip;
source.volume = 0;
source.loop = true;
// start the clip from a random point
source.time = Random.Range(0f, clip.length);
source.Play();
source.minDistance = 5;
source.maxDistance = maxRolloffDistance;
source.dopplerLevel = 0;
return source;
}
// unclamped versions of Lerp and Inverse Lerp, to allow value to exceed the from-to range
private static float ULerp(float from, float to, float value)
{
return (1.0f - value) * from + value * to;
}
}
}
using System.Collections; using UnityEngine;
namespace UnityStandardAssets.player2 { [RequireComponent(typeof(player2audio))] public class player2wheel : MonoBehaviour { public Transform SkidTrailPrefab; public static Transform skidTrailsDetachedParent; public ParticleSystem skidParticles; public bool skidding { get; private set; } public bool PlayingAudio { get; private set; }
private AudioSource m_AudioSource;
private Transform m_SkidTrail;
private WheelCollider m_WheelCollider;
private void Start()
{
skidParticles = transform.root.GetComponentInChildren<ParticleSystem>();
if (skidParticles == null)
{
Debug.LogWarning(" no particle system found on car to generate smoke particles", gameObject);
}
else
{
skidParticles.Stop();
}
m_WheelCollider = GetComponent<WheelCollider>();
m_AudioSource = GetComponent<AudioSource>();
PlayingAudio = false;
if (skidTrailsDetachedParent == null)
{
skidTrailsDetachedParent = new GameObject("Skid Trails - Detached").transform;
}
}
public void EmitTyreSmoke()
{
skidParticles.transform.position = transform.position - transform.up * m_WheelCollider.radius;
skidParticles.Emit(1);
if (!skidding)
{
StartCoroutine(StartSkidTrail());
}
}
public void PlayAudio()
{
m_AudioSource.Play();
PlayingAudio = true;
}
public void StopAudio()
{
m_AudioSource.Stop();
PlayingAudio = false;
}
public IEnumerator StartSkidTrail()
{
skidding = true;
m_SkidTrail = Instantiate(SkidTrailPrefab);
while (m_SkidTrail == null)
{
yield return null;
}
m_SkidTrail.parent = transform;
m_SkidTrail.localPosition = -Vector3.up * m_WheelCollider.radius;
}
public void EndSkidTrail()
{
if (!skidding)
{
return;
}
skidding = false;
m_SkidTrail.parent = skidTrailsDetachedParent;
Destroy(m_SkidTrail.gameObject, 10);
}
}
}
Your answer
Follow this Question
Related Questions
How to set lap timer for network multiplayer 0 Answers
Splitscreen w/ different GUIs on each camera 2 Answers
Automatic Car Moving Script 1 Answer
Smartfox Multiplayer Update problem 0 Answers