157 lines
5.8 KiB
C#
157 lines
5.8 KiB
C#
using RaceFields.CameraSystem;
|
|
using RaceFields.Vehicles;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace RaceFields.EditorTools
|
|
{
|
|
public static class BuggyPrefabBuilder
|
|
{
|
|
private const string BuggyPrefabPath = "Assets/_Project/Prefabs/Vehicles/Player/Buggy_Player.prefab";
|
|
private const string CameraPrefabPath = "Assets/_Project/Prefabs/Cameras/Buggy_ThirdPersonCamera.prefab";
|
|
|
|
[MenuItem("Race Fields/Setup/Rebuild Buggy Prefab")]
|
|
public static void RebuildBuggyPrefab()
|
|
{
|
|
GameObject root = PrefabUtility.LoadPrefabContents(BuggyPrefabPath);
|
|
try
|
|
{
|
|
EnsureComponent<Rigidbody>(root, ConfigureBody);
|
|
EnsureComponent<BoxCollider>(root, ConfigureBodyCollider);
|
|
EnsureComponent<ArcadeBuggyController>(root, null);
|
|
EnsureComponent<BuggyWheelSetup>(root, setup => setup.AlignAllWheels());
|
|
|
|
SetupWheel(root.transform, "F_L", "WheelCollider_FL");
|
|
SetupWheel(root.transform, "F_R", "WheelCollider_FR");
|
|
SetupWheel(root.transform, "B_L", "WheelCollider_RL");
|
|
SetupWheel(root.transform, "B_R", "WheelCollider_RR");
|
|
|
|
BuggyWheelSetup wheelSetup = root.GetComponent<BuggyWheelSetup>();
|
|
wheelSetup.AlignAllWheels();
|
|
|
|
PrefabUtility.SaveAsPrefabAsset(root, BuggyPrefabPath);
|
|
}
|
|
finally
|
|
{
|
|
PrefabUtility.UnloadPrefabContents(root);
|
|
}
|
|
|
|
RebuildCameraPrefab();
|
|
AssetDatabase.SaveAssets();
|
|
AssetDatabase.Refresh();
|
|
}
|
|
|
|
private static void RebuildCameraPrefab()
|
|
{
|
|
GameObject cameraObject = new GameObject("Buggy_ThirdPersonCamera");
|
|
try
|
|
{
|
|
Camera camera = cameraObject.AddComponent<Camera>();
|
|
camera.fieldOfView = 62f;
|
|
camera.nearClipPlane = 0.05f;
|
|
camera.farClipPlane = 600f;
|
|
cameraObject.AddComponent<AudioListener>();
|
|
cameraObject.AddComponent<BuggyFollowCamera>().SnapToTarget();
|
|
|
|
cameraObject.transform.position = new Vector3(0f, 4.2f, -7.5f);
|
|
cameraObject.transform.rotation = Quaternion.Euler(18f, 0f, 0f);
|
|
|
|
PrefabUtility.SaveAsPrefabAsset(cameraObject, CameraPrefabPath);
|
|
}
|
|
finally
|
|
{
|
|
Object.DestroyImmediate(cameraObject);
|
|
}
|
|
}
|
|
|
|
private static void SetupWheel(Transform root, string visualName, string colliderName)
|
|
{
|
|
Transform visual = FindDescendant(root, visualName);
|
|
if (visual == null)
|
|
{
|
|
Debug.LogWarning($"Wheel visual '{visualName}' was not found in {BuggyPrefabPath}.");
|
|
return;
|
|
}
|
|
|
|
Transform colliderTransform = FindDescendant(root, colliderName);
|
|
GameObject colliderObject = colliderTransform != null
|
|
? colliderTransform.gameObject
|
|
: new GameObject(colliderName);
|
|
|
|
colliderObject.name = colliderName;
|
|
colliderObject.transform.SetParent(root, true);
|
|
colliderObject.transform.position = visual.position;
|
|
colliderObject.transform.rotation = root.rotation;
|
|
colliderObject.transform.localScale = Vector3.one;
|
|
|
|
WheelCollider wheelCollider = colliderObject.GetComponent<WheelCollider>();
|
|
if (wheelCollider == null)
|
|
wheelCollider = colliderObject.AddComponent<WheelCollider>();
|
|
|
|
ConfigureWheel(wheelCollider, visual);
|
|
}
|
|
|
|
private static void ConfigureBody(Rigidbody body)
|
|
{
|
|
body.mass = 850f;
|
|
body.linearDamping = 0.05f;
|
|
body.angularDamping = 0.8f;
|
|
body.interpolation = RigidbodyInterpolation.Interpolate;
|
|
body.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
|
|
}
|
|
|
|
private static void ConfigureBodyCollider(BoxCollider collider)
|
|
{
|
|
collider.center = new Vector3(0f, 0.55f, 0f);
|
|
collider.size = new Vector3(1.8f, 0.9f, 3.1f);
|
|
}
|
|
|
|
private static void ConfigureWheel(WheelCollider wheelCollider, Transform visual)
|
|
{
|
|
wheelCollider.mass = 20f;
|
|
wheelCollider.radius = EstimateRadius(visual);
|
|
wheelCollider.suspensionDistance = 0.28f;
|
|
wheelCollider.forceAppPointDistance = 0.05f;
|
|
wheelCollider.wheelDampingRate = 0.35f;
|
|
|
|
JointSpring spring = wheelCollider.suspensionSpring;
|
|
spring.spring = 35000f;
|
|
spring.damper = 4500f;
|
|
spring.targetPosition = 0.5f;
|
|
wheelCollider.suspensionSpring = spring;
|
|
}
|
|
|
|
private static float EstimateRadius(Transform visual)
|
|
{
|
|
Renderer renderer = visual.GetComponentInChildren<Renderer>();
|
|
if (renderer == null)
|
|
return 0.34f;
|
|
|
|
Vector3 size = renderer.bounds.size;
|
|
return Mathf.Max(0.12f, Mathf.Max(size.y, size.z) * 0.5f);
|
|
}
|
|
|
|
private static T EnsureComponent<T>(GameObject gameObject, System.Action<T> configure) where T : Component
|
|
{
|
|
T component = gameObject.GetComponent<T>();
|
|
if (component == null)
|
|
component = gameObject.AddComponent<T>();
|
|
|
|
configure?.Invoke(component);
|
|
return component;
|
|
}
|
|
|
|
private static Transform FindDescendant(Transform root, string name)
|
|
{
|
|
Transform[] children = root.GetComponentsInChildren<Transform>(true);
|
|
for (int i = 0; i < children.Length; i++)
|
|
{
|
|
if (children[i].name == name)
|
|
return children[i];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
}
|