Files
my-project/Assets/charecter-controller/scripts/PlayerBuilderTool.cs
2026-04-15 02:56:11 +05:00

303 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.Animations;
public class PlayerBuilderTool : EditorWindow
{
// Модель
private GameObject characterModel;
private Transform headBone;
// Параметры движения
private float walkSpeed = 5f;
private float runSpeed = 9f;
private float crouchSpeed = 2.5f;
private float jumpHeight = 1.5f;
private float gravity = -9.81f;
// Коллайдер
private float height = 1.8f;
private float radius = 0.5f;
private float centerY = 0.9f;
// Камера
private bool addCamera = true;
private float cameraHeight = 1.7f;
// Анимации
private AnimationClip idleClip;
private AnimationClip walkClip;
private AnimationClip runClip;
private AnimationClip jumpClip;
private AnimationClip crouchIdleClip;
private AnimationClip crouchWalkClip;
// Аниматор контроллер
private AnimatorController animatorController;
private bool createAnimatorController = true;
[MenuItem("Tools/Player Builder")]
public static void ShowWindow()
{
GetWindow<PlayerBuilderTool>("Конструктор Персонажа");
}
void OnGUI()
{
GUILayout.Label("Настройки персонажа", EditorStyles.boldLabel);
// Секция модели
GUILayout.Label("Модель", EditorStyles.miniBoldLabel);
characterModel = (GameObject)EditorGUILayout.ObjectField("Модель персонажа", characterModel, typeof(GameObject), false);
headBone = (Transform)EditorGUILayout.ObjectField("Кость головы", headBone, typeof(Transform), true);
GUILayout.Space(10);
// Секция движения
GUILayout.Label("Движение", EditorStyles.miniBoldLabel);
walkSpeed = EditorGUILayout.FloatField("Скорость ходьбы", walkSpeed);
runSpeed = EditorGUILayout.FloatField("Скорость бега", runSpeed);
crouchSpeed = EditorGUILayout.FloatField("Скорость краулинга", crouchSpeed);
jumpHeight = EditorGUILayout.FloatField("Высота прыжка", jumpHeight);
gravity = EditorGUILayout.FloatField("Гравитация", gravity);
GUILayout.Space(10);
// Секция коллайдера
GUILayout.Label("Коллайдер", EditorStyles.miniBoldLabel);
height = EditorGUILayout.FloatField("Высота", height);
radius = EditorGUILayout.FloatField("Радиус", radius);
centerY = EditorGUILayout.FloatField("Центр Y", centerY);
GUILayout.Space(10);
// Секция камеры
GUILayout.Label("Камера", EditorStyles.miniBoldLabel);
addCamera = EditorGUILayout.Toggle("Добавить камеру", addCamera);
if (addCamera)
{
cameraHeight = EditorGUILayout.Slider("Высота камеры", cameraHeight, 1f, 2f);
}
GUILayout.Space(10);
// Секция анимаций
GUILayout.Label("Анимации", EditorStyles.miniBoldLabel);
createAnimatorController = EditorGUILayout.Toggle("Создать контроллер", createAnimatorController);
idleClip = (AnimationClip)EditorGUILayout.ObjectField("Idle", idleClip, typeof(AnimationClip), false);
walkClip = (AnimationClip)EditorGUILayout.ObjectField("Walk", walkClip, typeof(AnimationClip), false);
runClip = (AnimationClip)EditorGUILayout.ObjectField("Run", runClip, typeof(AnimationClip), false);
jumpClip = (AnimationClip)EditorGUILayout.ObjectField("Jump", jumpClip, typeof(AnimationClip), false);
crouchIdleClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Idle", crouchIdleClip, typeof(AnimationClip), false);
crouchWalkClip = (AnimationClip)EditorGUILayout.ObjectField("Crouch Walk", crouchWalkClip, typeof(AnimationClip), false);
if (characterModel != null)
{
var animator = characterModel.GetComponent<Animator>();
if (animator != null && animator.avatar != null)
{
EditorGUILayout.HelpBox("Модель содержит Animator - аватар будет скопирован", MessageType.Info);
}
}
GUILayout.Space(20);
// Кнопки действий
GUI.color = Color.green;
if (GUILayout.Button("Создать в сцене"))
{
BuildPlayer("Player");
}
GUI.color = Color.cyan;
if (GUILayout.Button("Сохранить как префаб"))
{
SaveAsPrefab();
}
GUI.color = Color.yellow;
if (GUILayout.Button("Создать с тестовой моделью (капсула)"))
{
BuildTestPlayer();
}
GUI.color = Color.white;
GUILayout.Space(10);
EditorGUILayout.HelpBox(
"1. Назначьте модель персонажа\n" +
"2. Назначьте анимации (опционально)\n" +
"3. Настройте параметры\n" +
"4. Нажмите 'Создать в сцене'",
MessageType.Info);
}
void BuildPlayer(string playerName)
{
GameObject player = new GameObject(playerName);
// CharacterController
var cc = player.AddComponent<CharacterController>();
cc.height = height;
cc.radius = radius;
cc.center = new Vector3(0, centerY, 0);
// Скрипт персонажа
var character = player.AddComponent<charecter>();
character.walkSpeed = walkSpeed;
character.runSpeed = runSpeed;
character.crouchSpeed = crouchSpeed;
character.jumpHeight = jumpHeight;
character.gravity = gravity;
// Модель
GameObject model = null;
if (characterModel != null)
{
model = Instantiate(characterModel, player.transform);
model.transform.localPosition = Vector3.zero;
model.transform.localRotation = Quaternion.identity;
// Голова
if (headBone != null)
{
character.head = headBone;
}
else
{
character.head = FindChildBone(model.transform, "Head");
}
//Animator
var modelAnimator = model.GetComponent<Animator>();
if (modelAnimator != null && modelAnimator.avatar != null)
{
var animator = player.AddComponent<Animator>();
animator.avatar = modelAnimator.avatar;
}
}
// Голова если не найдена
if (character.head == null)
{
GameObject headObj = new GameObject("HeadPoint");
headObj.transform.SetParent(model != null ? model.transform : player.transform);
headObj.transform.localPosition = new Vector3(0, height - 0.2f, 0);
character.head = headObj.transform;
}
// Камера
if (addCamera && character.head != null)
{
GameObject cameraObj = new GameObject("PlayerCamera");
cameraObj.transform.SetParent(character.head);
cameraObj.transform.localPosition = new Vector3(0, 0.1f, 0);
var cam = cameraObj.AddComponent<Camera>();
cam.tag = "MainCamera";
cam.nearClipPlane = 0.1f;
// Удалить старую
var oldCam = GameObject.FindWithTag("MainCamera");
if (oldCam != null && oldCam != cameraObj)
{
DestroyImmediate(oldCam);
}
}
// Тег
player.tag = "Player";
// Позиция
player.transform.position = new Vector3(0, 2, -5);
Selection.activeGameObject = player;
Debug.Log($"[PlayerBuilder] Создан: {playerName}");
}
void SaveAsPrefab()
{
string path = EditorUtility.SaveFilePanelInProject(
"Сохранить префаб",
"Player",
"prefab",
"Выберите место");
if (string.IsNullOrEmpty(path)) return;
BuildPlayer("PlayerTemp");
GameObject player = GameObject.Find("PlayerTemp");
if (player == null)
{
Debug.LogError("Не удалось создать игрока");
return;
}
GameObject prefab = PrefabUtility.SaveAsPrefabAsset(player, path);
DestroyImmediate(player);
Selection.activeObject = prefab;
Debug.Log($"[PlayerBuilder] Сохранено: {path}");
}
void BuildTestPlayer()
{
characterModel = null;
headBone = null;
BuildPlayer("TestPlayer");
GameObject player = Selection.activeGameObject;
if (player == null) return;
// Создаём визуальную часть
GameObject body = GameObject.CreatePrimitive(PrimitiveType.Capsule);
body.name = "Body";
body.transform.SetParent(player.transform);
body.transform.localPosition = Vector3.zero;
DestroyImmediate(body.GetComponent<Collider>());
GameObject head = new GameObject("Head");
head.transform.SetParent(player.transform);
head.transform.localPosition = new Vector3(0, centerY + 0.2f, 0);
var character = player.GetComponent<charecter>();
if (character != null)
{
character.head = head.transform;
}
if (addCamera)
{
GameObject camObj = new GameObject("PlayerCamera");
camObj.transform.SetParent(head.transform);
camObj.transform.localPosition = new Vector3(0, 0.1f, 0);
var cam = camObj.AddComponent<Camera>();
cam.tag = "MainCamera";
var oldCam = GameObject.FindWithTag("MainCamera");
if (oldCam != null && oldCam != camObj)
{
DestroyImmediate(oldCam);
}
}
Debug.Log("[PlayerBuilder] Создан тестовый игрок");
}
Transform FindChildBone(Transform parent, string boneName)
{
if (parent == null) return null;
if (parent.name.ToLower().Contains(boneName.ToLower()))
return parent;
foreach (Transform child in parent)
{
var result = FindChildBone(child, boneName);
if (result != null) return result;
}
return null;
}
}