车辆车轮控制
作者:互联网
using UnityEngine;
using System.Collections.Generic;
namespace RGSK
{
public class Wheels : MonoBehaviour
{
private SurfaceManager surfaceManager;
private Texture2D currentTexture;
private PhysicMaterial currentPhysicMaterial;
private WheelCollider wheelCollider;
private WheelHit wheelHit;
private Skidmark skidmarks;
private int lastSkid;
private Terrain terrain;
private TerrainData terrainData;
private SplatPrototype[] splatPrototypes;
private AudioSource skidAudioSource;
[HideInInspector]
public bool shouldEmit = false;
[HideInInspector]
public bool wheelOnPenaltySurface;
private ParticleSystem particleToEmit;
private bool useSkidmarks;
private List<string> wheelParticleChildren = new List<string>();
void Start()
{
//Get the surface manager
if (GameObject.FindObjectOfType(typeof(SurfaceManager)))
{
surfaceManager = GameObject.FindObjectOfType(typeof(SurfaceManager)) as SurfaceManager;
}
else
{
return; //如果没有则不返回参数
}
SetupWheelComponents();
GetTerrainInfo(); //获取地形信息
}
void SetupWheelComponents()
{
if (!wheelCollider)
wheelCollider = GetComponent<WheelCollider>();
//Get the skidmarks object
if (GameObject.FindObjectOfType(typeof(Skidmark)))
{
skidmarks = GameObject.FindObjectOfType(typeof(Skidmark)) as Skidmark;
}
//Configure the sound
if (GetComponent<AudioSource>()) skidAudioSource = GetComponent<AudioSource>();
if (skidAudioSource)
{
skidAudioSource.spatialBlend = 1.0f;
skidAudioSource.loop = true;
}
//将所有的地形实例为子对象
if (surfaceManager.terrainSurfaceTypes.Count > 0)
{
for (int i = 0; i < surfaceManager.terrainSurfaceTypes.Count; i++)
{
if (surfaceManager.terrainSurfaceTypes[i].skidParticle)
{
if (!wheelParticleChildren.Contains(surfaceManager.terrainSurfaceTypes[i].skidParticle.transform.name + "(Clone)")) //确保无副本
{
GameObject particle = (GameObject)Instantiate(surfaceManager.terrainSurfaceTypes[i].skidParticle, transform.position, Quaternion.identity);
particle.transform.parent = transform;
var em = particle.GetComponent<ParticleSystem>().emission;
em.enabled = false;
wheelParticleChildren.Add(particle.transform.name);
}
}
}
}
//将所有的物理材质实例为子对象
if (surfaceManager.physicMaterialSurface.Count > 0)
{
for (int i = 0; i < surfaceManager.physicMaterialSurface.Count; i++)
{
if (surfaceManager.physicMaterialSurface[i].skidParticle)
{
if (!wheelParticleChildren.Contains(surfaceManager.physicMaterialSurface[i].skidParticle.transform.name + "(Clone)")) //确保无副本
{
GameObject particle = (GameObject)Instantiate(surfaceManager.physicMaterialSurface[i].skidParticle, transform.position, Quaternion.identity);
particle.transform.parent = transform;
var em = particle.GetComponent<ParticleSystem>().emission;
em.enabled = false;
wheelParticleChildren.Add(particle.transform.name);
}
}
}
}
}
void Update()
{
if (!surfaceManager) return;
if (skidAudioSource && !skidAudioSource.isPlaying) //确保音乐一直循环
skidAudioSource.Play();
wheelCollider.GetGroundHit(out wheelHit); //获取轮胎碰撞数据
//Get the surfaces
PhysicMaterialSurfaceDetection(); //获取物理材质信息
TerrainSurfaceDetection(); //获取地形信息
Emit(); //发射粒子
}
void PhysicMaterialSurfaceDetection()
{
if (wheelHit.collider)
{
//Are we on a renderer
if (wheelHit.collider.material) //如果对象存在材质
{
currentPhysicMaterial = wheelHit.collider.material; //则将当前材质设定为对应材质的对应材质
for (int i = 0; i < surfaceManager.physicMaterialSurface.Count; i++) //遍历材质系统,寻找是否有对应的材质
{
if (currentPhysicMaterial.name.Replace(" (Instance)", "") == surfaceManager.physicMaterialSurface[i].physicMaterial.name)
{
//播放对应材质的音效
if (skidAudioSource && surfaceManager.physicMaterialSurface[i].skidSound) skidAudioSource.clip = surfaceManager.physicMaterialSurface[i].skidSound;
// 发射对应材质的粒子
foreach (Transform t in transform)
{
if (t.name == surfaceManager.physicMaterialSurface[i].skidParticle.name + "(Clone)")
particleToEmit = t.GetComponent<ParticleSystem>();
}
//判断表面类型是否是连续的
if (surfaceManager.physicMaterialSurface[i].surfaceType == SurfaceManager.SurfaceType.OffRoad)
{
if (skidAudioSource && wheelCollider.attachedRigidbody.velocity.magnitude > 5.0f) { shouldEmit = true; skidAudioSource.volume = .5f; }
}
//判断当前平面是否需要使用滑动痕迹
useSkidmarks = surfaceManager.physicMaterialSurface[i].allowSkidmark;
wheelOnPenaltySurface = surfaceManager.physicMaterialSurface[i].isPenaltySurface;
}
}
}
}
}
void TerrainSurfaceDetection()
{
if (terrain == null) return; //如果地形为空则直接返回
if (wheelHit.collider) //判断当前是否与地面相接触
{
if (wheelHit.collider.GetComponent<Terrain>()) //当与地面相接触时,将对应的材质返回
{
currentTexture = splatPrototypes[GetTerrainTexture(transform.position)].texture;
}
else //没有接触时,则不返回
{
currentTexture = null;
}
}
for (int i = 0; i < surfaceManager.terrainSurfaceTypes.Count; i++) //设定或返回地面材质的细节数据
{
if (currentTexture == surfaceManager.terrainSurfaceTypes[i].texture)
{
//返回对应材质的音效,并进行播放
if (surfaceManager.terrainSurfaceTypes[i].skidSound)
{
if (skidAudioSource && surfaceManager.terrainSurfaceTypes[i].skidSound) skidAudioSource.clip = surfaceManager.terrainSurfaceTypes[i].skidSound;
}
// 发射对应的粒子
foreach (Transform t in transform)
{
if (t.name == surfaceManager.terrainSurfaceTypes[i].skidParticle.name + "(Clone)")
{
particleToEmit = t.GetComponent<ParticleSystem>();
}
}
//判断表面是否是连续的
if (surfaceManager.terrainSurfaceTypes[i].surfaceType == SurfaceManager.SurfaceType.OffRoad)
{
if (skidAudioSource && wheelCollider.attachedRigidbody.velocity.magnitude > 5.0f) { shouldEmit = true; skidAudioSource.volume = .5f; }
}
//判断是否能够使用滑动痕迹
useSkidmarks = surfaceManager.terrainSurfaceTypes[i].allowSkidmark;
wheelOnPenaltySurface = surfaceManager.terrainSurfaceTypes[i].isPenaltySurface;
}
}
}
public void Emit() //发射系统
{
if (shouldEmit && wheelCollider.isGrounded) //当允许发射,且车辆着地时
{
//粒子
if (particleToEmit) particleToEmit.Emit(1);
//滑动痕迹
Vector3 skidPoint = wheelHit.point + (wheelCollider.attachedRigidbody.velocity * Time.fixedDeltaTime);
if (skidmarks != null)
{
if (useSkidmarks)
lastSkid = skidmarks.AddSkidMark(skidPoint, wheelHit.normal, 0.5f, lastSkid);
else
lastSkid = -1;
}
//音效的音量
if (skidAudioSource)
skidAudioSource.volume = Mathf.Abs(wheelHit.sidewaysSlip) + Mathf.Abs(wheelHit.forwardSlip) + 0.5f;
}
else
{
lastSkid = -1;
//声音的线性差值
if (skidAudioSource)
skidAudioSource.volume -= Time.deltaTime;
}
}
//与地形相关的方法
private void GetTerrainInfo() //获取地形信息
{
if (Terrain.activeTerrain)
{
terrain = Terrain.activeTerrain;
terrainData = terrain.terrainData;
splatPrototypes = terrain.terrainData.splatPrototypes;
}
}
private float[] GetTextureMix(Vector3 worldPos) //获得纹理
{
terrain = Terrain.activeTerrain; //激活地形
terrainData = terrain.terrainData; //获取数据
Vector3 terrainPos = terrain.transform.position; //获取地形的位置信息
int mapX = (int)(((worldPos.x - terrainPos.x) / terrainData.size.x) * terrainData.alphamapWidth);
int mapZ = (int)(((worldPos.z - terrainPos.z) / terrainData.size.z) * terrainData.alphamapHeight);
float[,,] splatmapData = terrainData.GetAlphamaps(mapX, mapZ, 1, 1); //将地形的位置数据传递给贴图的位置数据
float[] cellMix = new float[splatmapData.GetUpperBound(2) + 1]; //存储获得的数据
for (int n = 0; n < cellMix.Length; ++n) //遍历每一个数据,并将其返回
{
cellMix[n] = splatmapData[0, 0, n];
}
return cellMix;
}
private int GetTerrainTexture(Vector3 worldPos) //获得地面的纹理
{
float[] mix = GetTextureMix(worldPos);
float maxMix = 0;
int maxIndex = 0;
for (int n = 0; n < mix.Length; ++n)
{
if (mix[n] > maxMix)
{
maxIndex = n;
maxMix = mix[n];
}
}
return maxIndex;
}
public void SetupWheelCollider(float mass, float spring, float damper) //设定轮胎的重量,弹簧以及减震器
{
if (!wheelCollider)
wheelCollider = GetComponent<WheelCollider>();
JointSpring _spring = wheelCollider.suspensionSpring;
_spring.spring = spring;
_spring.damper = damper;
wheelCollider.suspensionSpring = _spring;
wheelCollider.mass = mass;
wheelCollider.wheelDampingRate = 1.0f;
}
}
}
标签:surfaceManager,控制,wheelCollider,transform,private,terrainSurfaceTypes,车辆,skidAud 来源: https://blog.csdn.net/kuyineko/article/details/116330548