Copie depuis Unity VCS vers GitHub
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f853990e5772f884290f13fd6d8555b0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,348 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Controller
|
||||
{
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
[RequireComponent(typeof(Animator))]
|
||||
[DisallowMultipleComponent]
|
||||
public class CharacterMover : MonoBehaviour
|
||||
{
|
||||
[Header("Movement")]
|
||||
[SerializeField]
|
||||
private float m_WalkSpeed = 1f;
|
||||
[SerializeField]
|
||||
private float m_RunSpeed = 4f;
|
||||
[SerializeField, Range(0f, 360f)]
|
||||
private float m_RotateSpeed = 90f;
|
||||
[SerializeField]
|
||||
private Space m_Space = Space.Self;
|
||||
[SerializeField]
|
||||
private float m_JumpHeight = 5f;
|
||||
|
||||
[Header("Animator")]
|
||||
[SerializeField]
|
||||
private string m_HorizontalID = "Hor";
|
||||
[SerializeField]
|
||||
private string m_VerticalID = "Vert";
|
||||
[SerializeField]
|
||||
private string m_StateID = "State";
|
||||
[SerializeField]
|
||||
private string m_JumpID = "IsJump";
|
||||
[SerializeField]
|
||||
private LookWeight m_LookWeight = new(1f, 0.3f, 0.7f, 1f);
|
||||
|
||||
private Transform m_Transform;
|
||||
private CharacterController m_Controller;
|
||||
private Animator m_Animator;
|
||||
|
||||
private MovementHandler m_Movement;
|
||||
private AnimationHandler m_Animation;
|
||||
|
||||
private Vector2 m_Axis;
|
||||
private Vector3 m_Target;
|
||||
private bool m_IsRun;
|
||||
private bool m_IsJump;
|
||||
|
||||
private bool m_IsMoving;
|
||||
|
||||
public Vector2 Axis => m_Axis;
|
||||
public Vector3 Target => m_Target;
|
||||
public bool IsRun => m_IsRun;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
m_WalkSpeed = Mathf.Max(m_WalkSpeed, 0f);
|
||||
m_RunSpeed = Mathf.Max(m_RunSpeed, m_WalkSpeed);
|
||||
|
||||
m_Movement?.SetStats(m_WalkSpeed / 3.6f, m_RunSpeed / 3.6f, m_RotateSpeed, m_JumpHeight, m_Space);
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
m_Transform = transform;
|
||||
m_Controller = GetComponent<CharacterController>();
|
||||
m_Animator = GetComponent<Animator>();
|
||||
|
||||
m_Movement = new MovementHandler(m_Controller, m_Transform, m_WalkSpeed, m_RunSpeed, m_RotateSpeed, m_JumpHeight, m_Space);
|
||||
m_Animation = new AnimationHandler(m_Animator, m_HorizontalID, m_VerticalID, m_StateID, m_JumpID);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
m_Movement.Move(Time.deltaTime, in m_Axis, in m_Target, m_IsRun, m_IsJump, m_IsMoving, out var animAxis, out var isAir);
|
||||
m_Animation.Animate(in animAxis, m_IsRun? 1f : 0f, isAir, Time.deltaTime);
|
||||
|
||||
}
|
||||
|
||||
private void OnAnimatorIK()
|
||||
{
|
||||
m_Animation.AnimateIK(in m_Target, m_LookWeight);
|
||||
}
|
||||
|
||||
public void SetInput(in Vector2 axis, in Vector3 target, in bool isRun, in bool isJump)
|
||||
{
|
||||
m_Axis = axis;
|
||||
m_Target = target;
|
||||
m_IsRun = isRun;
|
||||
m_IsJump = isJump;
|
||||
|
||||
if (m_Axis.sqrMagnitude < Mathf.Epsilon)
|
||||
{
|
||||
m_Axis = Vector2.zero;
|
||||
m_IsMoving = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Axis = Vector3.ClampMagnitude(m_Axis, 1f);
|
||||
m_IsMoving = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnControllerColliderHit(ControllerColliderHit hit)
|
||||
{
|
||||
if(hit.normal.y > m_Controller.stepOffset)
|
||||
{
|
||||
m_Movement.SetSurface(hit.normal);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private struct LookWeight
|
||||
{
|
||||
public float weight;
|
||||
public float body;
|
||||
public float head;
|
||||
public float eyes;
|
||||
|
||||
public LookWeight(float weight, float body, float head, float eyes)
|
||||
{
|
||||
this.weight = weight;
|
||||
this.body = body;
|
||||
this.head = head;
|
||||
this.eyes = eyes;
|
||||
}
|
||||
}
|
||||
|
||||
#region Handlers
|
||||
private class MovementHandler
|
||||
{
|
||||
private readonly CharacterController m_Controller;
|
||||
private readonly Transform m_Transform;
|
||||
|
||||
private float m_WalkSpeed;
|
||||
private float m_RunSpeed;
|
||||
private float m_RotateSpeed;
|
||||
private float m_JumpHeight;
|
||||
|
||||
private Space m_Space;
|
||||
|
||||
private readonly float m_Luft = 75f;
|
||||
private readonly float m_JumpReload = 1f;
|
||||
|
||||
private float m_TargetAngle;
|
||||
private bool m_IsRotating = false;
|
||||
|
||||
private Vector3 m_Normal;
|
||||
private Vector3 m_GravityAcelleration = Physics.gravity;
|
||||
|
||||
private float m_jumpTimer;
|
||||
|
||||
public MovementHandler(CharacterController controller, Transform transform, float walkSpeed, float runSpeed, float rotateSpeed, float jumpHeight, Space space)
|
||||
{
|
||||
m_Controller = controller;
|
||||
m_Transform = transform;
|
||||
|
||||
m_WalkSpeed = walkSpeed;
|
||||
m_RunSpeed = runSpeed;
|
||||
m_RotateSpeed = rotateSpeed;
|
||||
m_JumpHeight = jumpHeight;
|
||||
|
||||
m_Space = space;
|
||||
}
|
||||
|
||||
public void SetStats(float walkSpeed, float runSpeed, float rotateSpeed, float jumpHeight, Space space)
|
||||
{
|
||||
m_WalkSpeed = walkSpeed;
|
||||
m_RunSpeed = runSpeed;
|
||||
m_RotateSpeed = rotateSpeed;
|
||||
m_JumpHeight = jumpHeight;
|
||||
|
||||
m_Space = space;
|
||||
}
|
||||
|
||||
public void SetSurface(in Vector3 normal)
|
||||
{
|
||||
m_Normal = normal;
|
||||
}
|
||||
|
||||
public void Move(float deltaTime, in Vector2 axis, in Vector3 target, bool isRun, bool isJump, bool isMoving, out Vector2 animAxis, out bool isAir)
|
||||
{
|
||||
var targetForward = Vector3.Normalize(target - m_Transform.position);
|
||||
|
||||
ConvertMovement(in axis, in targetForward, out var movement);
|
||||
CaculateGravity(isJump, deltaTime, out isAir);
|
||||
Displace(deltaTime, in movement, isRun);
|
||||
Turn(in targetForward, isMoving);
|
||||
UpdateRotation(deltaTime);
|
||||
|
||||
GenAnimationAxis(in movement, out animAxis);
|
||||
}
|
||||
|
||||
private void ConvertMovement(in Vector2 axis, in Vector3 targetForward, out Vector3 movement)
|
||||
{
|
||||
Vector3 forward;
|
||||
Vector3 right;
|
||||
|
||||
if (m_Space == Space.Self)
|
||||
{
|
||||
forward = new Vector3(targetForward.x, 0f, targetForward.z).normalized;
|
||||
right = Vector3.Cross(Vector3.up, forward).normalized;
|
||||
}
|
||||
else
|
||||
{
|
||||
forward = Vector3.forward;
|
||||
right = Vector3.right;
|
||||
}
|
||||
|
||||
movement = axis.x * right + axis.y * forward;
|
||||
movement = Vector3.ProjectOnPlane(movement, m_Normal);
|
||||
}
|
||||
|
||||
private void Displace(float deltaTime, in Vector3 movement, bool isRun)
|
||||
{
|
||||
Vector3 displacement = (isRun ? m_RunSpeed : m_WalkSpeed) * movement;
|
||||
displacement += m_GravityAcelleration;
|
||||
displacement *= deltaTime;
|
||||
|
||||
m_Controller.Move(displacement);
|
||||
}
|
||||
|
||||
private void CaculateGravity(bool isJump, float deltaTime, out bool isAir)
|
||||
{
|
||||
m_jumpTimer = Mathf.Max(m_jumpTimer - deltaTime, 0f);
|
||||
|
||||
if (m_Controller.isGrounded)
|
||||
{
|
||||
if (isJump && m_jumpTimer <= 0)
|
||||
{
|
||||
var gravity = Physics.gravity;
|
||||
var length = gravity.magnitude;
|
||||
|
||||
m_GravityAcelleration += -(gravity / length) * Mathf.Sqrt(m_JumpHeight * 6f * length);
|
||||
m_jumpTimer = m_JumpReload;
|
||||
isAir = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_GravityAcelleration = Physics.gravity;
|
||||
isAir = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
isAir = true;
|
||||
|
||||
m_GravityAcelleration += Physics.gravity * deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
private void GenAnimationAxis(in Vector3 movement, out Vector2 animAxis)
|
||||
{
|
||||
if(m_Space == Space.Self)
|
||||
{
|
||||
animAxis = new Vector2(Vector3.Dot(movement, m_Transform.right), Vector3.Dot(movement, m_Transform.forward));
|
||||
}
|
||||
else
|
||||
{
|
||||
animAxis = new Vector2(Vector3.Dot(movement, Vector3.right), Vector3.Dot(movement, Vector3.forward));
|
||||
}
|
||||
}
|
||||
|
||||
private void Turn(in Vector3 targetForward, bool isMoving)
|
||||
{
|
||||
var angle = Vector3.SignedAngle(m_Transform.forward, Vector3.ProjectOnPlane(targetForward, Vector3.up), Vector3.up);
|
||||
|
||||
if (!m_IsRotating)
|
||||
{
|
||||
if (!isMoving && Mathf.Abs(angle) < m_Luft)
|
||||
{
|
||||
m_IsRotating = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_IsRotating = true;
|
||||
}
|
||||
|
||||
m_TargetAngle = angle;
|
||||
}
|
||||
|
||||
private void UpdateRotation(float deltaTime)
|
||||
{
|
||||
if(!m_IsRotating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var rotDelta = m_RotateSpeed * deltaTime;
|
||||
if (rotDelta + Mathf.PI * 2f + Mathf.Epsilon >= Mathf.Abs(m_TargetAngle))
|
||||
{
|
||||
rotDelta = m_TargetAngle;
|
||||
m_IsRotating = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotDelta *= Mathf.Sign(m_TargetAngle);
|
||||
}
|
||||
|
||||
m_Transform.Rotate(Vector3.up, rotDelta);
|
||||
}
|
||||
}
|
||||
|
||||
private class AnimationHandler
|
||||
{
|
||||
private readonly Animator m_Animator;
|
||||
|
||||
private readonly string m_HorizontalID;
|
||||
private readonly string m_VerticalID;
|
||||
private readonly string m_StateID;
|
||||
private readonly string m_JumpID;
|
||||
|
||||
private readonly float k_InputFlow = 4.5f;
|
||||
|
||||
private float m_FlowState;
|
||||
private Vector2 m_FlowAxis;
|
||||
|
||||
public AnimationHandler(Animator animator, string horizontalID, string verticalID, string stateID, string jumpID)
|
||||
{
|
||||
m_Animator = animator;
|
||||
|
||||
m_HorizontalID = horizontalID;
|
||||
m_VerticalID = verticalID;
|
||||
m_StateID = stateID;
|
||||
m_JumpID = jumpID;
|
||||
}
|
||||
|
||||
public void Animate(in Vector2 axis, float state, bool isJump, float deltaTime)
|
||||
{
|
||||
|
||||
m_Animator.SetFloat(m_HorizontalID, m_FlowAxis.x);
|
||||
m_Animator.SetFloat(m_VerticalID, m_FlowAxis.y);
|
||||
|
||||
m_Animator.SetFloat(m_StateID, Mathf.Clamp01(m_FlowState));
|
||||
m_Animator.SetBool(m_JumpID, isJump);
|
||||
|
||||
m_FlowAxis = Vector2.ClampMagnitude(m_FlowAxis + k_InputFlow * deltaTime * (axis - m_FlowAxis).normalized, 1f);
|
||||
m_FlowState = Mathf.Clamp01(m_FlowState + k_InputFlow * deltaTime * Mathf.Sign(state - m_FlowState));
|
||||
}
|
||||
|
||||
public void AnimateIK(in Vector3 target, in LookWeight lookWeight)
|
||||
{
|
||||
m_Animator.SetLookAtPosition(target);
|
||||
m_Animator.SetLookAtWeight(lookWeight.weight, lookWeight.body, lookWeight.head, lookWeight.eyes);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f75db5b538eef814b9775d744f05e3b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Character_Controller/CharacterMover.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,86 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Controller
|
||||
{
|
||||
[RequireComponent(typeof(CharacterMover))]
|
||||
public class MovePlayerInput : MonoBehaviour
|
||||
{
|
||||
[Header("Character")]
|
||||
[SerializeField]
|
||||
private string m_HorizontalAxis = "Horizontal";
|
||||
[SerializeField]
|
||||
private string m_VerticalAxis = "Vertical";
|
||||
[SerializeField]
|
||||
private string m_JumpButton = "Jump";
|
||||
[SerializeField]
|
||||
private KeyCode m_RunKey = KeyCode.LeftShift;
|
||||
|
||||
[Header("Camera")]
|
||||
[SerializeField]
|
||||
private PlayerCamera m_Camera;
|
||||
[SerializeField]
|
||||
private string m_MouseX = "Mouse X";
|
||||
[SerializeField]
|
||||
private string m_MouseY = "Mouse Y";
|
||||
[SerializeField]
|
||||
private string m_MouseScroll = "Mouse ScrollWheel";
|
||||
|
||||
private CharacterMover m_Mover;
|
||||
|
||||
private Vector2 m_Axis;
|
||||
private bool m_IsRun;
|
||||
private bool m_IsJump;
|
||||
|
||||
private Vector3 m_Target;
|
||||
private Vector2 m_MouseDelta;
|
||||
private float m_Scroll;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
m_Mover = GetComponent<CharacterMover>();
|
||||
|
||||
if(m_Camera == null )
|
||||
{
|
||||
m_Camera = Camera.main == null ? null : Camera.main.GetComponent<PlayerCamera>();
|
||||
}
|
||||
if(m_Camera != null) {
|
||||
m_Camera.SetPlayer(transform);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
GatherInput();
|
||||
SetInput();
|
||||
}
|
||||
|
||||
public void GatherInput()
|
||||
{
|
||||
m_Axis = new Vector2(Input.GetAxis(m_HorizontalAxis), Input.GetAxis(m_VerticalAxis));
|
||||
m_IsRun = Input.GetKey(m_RunKey);
|
||||
m_IsJump = Input.GetButton(m_JumpButton);
|
||||
|
||||
m_Target = (m_Camera == null) ? Vector3.zero : m_Camera.Target;
|
||||
m_MouseDelta = new Vector2(Input.GetAxis(m_MouseX), Input.GetAxis(m_MouseY));
|
||||
m_Scroll = Input.GetAxis(m_MouseScroll);
|
||||
}
|
||||
|
||||
public void BindMover(CharacterMover mover)
|
||||
{
|
||||
m_Mover = mover;
|
||||
}
|
||||
|
||||
public void SetInput()
|
||||
{
|
||||
if (m_Mover != null)
|
||||
{
|
||||
m_Mover.SetInput(in m_Axis, in m_Target, in m_IsRun, m_IsJump);
|
||||
}
|
||||
|
||||
if (m_Camera != null)
|
||||
{
|
||||
m_Camera.SetInput(in m_MouseDelta, m_Scroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2c67ce836140b4479603ebcf944cddd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Character_Controller/MovePlayerInput.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,64 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Controller
|
||||
{
|
||||
public abstract class PlayerCamera : MonoBehaviour
|
||||
{
|
||||
private const float MIN_DISTANCE = 1f;
|
||||
private const float MAX_DISTANCE = 10f;
|
||||
|
||||
private const float TARGET_DISTANCE = MAX_DISTANCE * 2f;
|
||||
|
||||
protected Transform m_Player;
|
||||
|
||||
[SerializeField, Range(0f, 1f)]
|
||||
private float m_SensitivityX = 0.1f;
|
||||
[SerializeField, Range(0f, 1f)]
|
||||
private float m_SensitivityY = 0.1f;
|
||||
|
||||
[SerializeField, Range(0f, 1f)]
|
||||
private float m_Zoom = 0.5f;
|
||||
[SerializeField, Range(0f, 1f)]
|
||||
private float m_SensetivityZoom = 0.1f;
|
||||
|
||||
[SerializeField, Range(0, 90f)]
|
||||
private float m_MinAngle = 0f;
|
||||
[SerializeField, Range(0, 90f)]
|
||||
private float m_MaxAngle = 50f;
|
||||
|
||||
protected Transform m_Target;
|
||||
protected Transform m_Transform;
|
||||
|
||||
protected Vector2 m_Angles;
|
||||
protected float m_Distance;
|
||||
|
||||
public Vector3 Target => m_Target.position;
|
||||
public float TargetDistance => TARGET_DISTANCE;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
m_Transform = transform;
|
||||
|
||||
m_Target = new GameObject($"Target_{gameObject.name}").transform;
|
||||
if(m_Transform.parent != null)
|
||||
{
|
||||
m_Target.transform.parent = m_Transform.parent;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPlayer(Transform player) {
|
||||
m_Player = player;
|
||||
}
|
||||
|
||||
public virtual void SetInput(in Vector2 delta, float scroll)
|
||||
{
|
||||
m_Angles += new Vector2(delta.y * m_SensitivityY, delta.x * m_SensitivityX) * 360f;
|
||||
m_Angles.x = Mathf.Clamp(m_Angles.x, m_MinAngle, m_MaxAngle);
|
||||
|
||||
m_Zoom += scroll * m_SensetivityZoom;
|
||||
m_Zoom = Mathf.Clamp01(m_Zoom);
|
||||
|
||||
m_Distance = (1f - m_Zoom) * (MAX_DISTANCE - MIN_DISTANCE) + MIN_DISTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e64ae1274b15fa4fbea3733685f5b29
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Character_Controller/PlayerCamera.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,65 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Controller
|
||||
{
|
||||
public class ThirdPersonCamera : PlayerCamera
|
||||
{
|
||||
[SerializeField, Range(0f, 2f)]
|
||||
private float m_Offset = 1.5f;
|
||||
[SerializeField, Range(0f, 360f)]
|
||||
private float m_CameraSpeed = 90f;
|
||||
|
||||
private Vector3 m_LookPoint;
|
||||
private Vector3 m_TargetPos;
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
Move(Time.deltaTime);
|
||||
}
|
||||
|
||||
public override void SetInput(in Vector2 delta, float scroll)
|
||||
{
|
||||
base.SetInput(delta, scroll);
|
||||
|
||||
var dir = new Vector3(0, 0, -m_Distance);
|
||||
var rot = Quaternion.Euler(m_Angles.x, m_Angles.y, 0f);
|
||||
|
||||
var playerPos = (m_Player == null) ? Vector3.zero : m_Player.position;
|
||||
m_LookPoint = playerPos + m_Offset * Vector3.up;
|
||||
m_TargetPos = m_LookPoint + rot * dir;
|
||||
}
|
||||
|
||||
private void Move(float deltaTime)
|
||||
{
|
||||
camera();
|
||||
target();
|
||||
|
||||
void camera()
|
||||
{
|
||||
var direction = m_TargetPos - m_Transform.position;
|
||||
var delta = m_CameraSpeed * deltaTime;
|
||||
|
||||
if(delta * delta > direction.sqrMagnitude)
|
||||
{
|
||||
m_Transform.position = m_TargetPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Transform.position += delta * direction.normalized;
|
||||
}
|
||||
|
||||
m_Transform.LookAt(m_LookPoint);
|
||||
}
|
||||
|
||||
void target()
|
||||
{
|
||||
if(m_Target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Target.position = m_Transform.position + m_Transform.forward * TargetDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7f4329458cdb464796191393167d4f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Character_Controller/ThirdPersonCamera.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e288d36454b64b945931064f52313219
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor
|
||||
{
|
||||
public static class AssetLoader
|
||||
{
|
||||
public static IEnumerable<T> LoadAssets<T>(string filter, string folder)
|
||||
where T : Object
|
||||
{
|
||||
var assets = AssetDatabase.FindAssets(filter, new[] { folder })
|
||||
.Select(AssetDatabase.GUIDToAssetPath)
|
||||
.Select(AssetDatabase.LoadAssetAtPath<T>)
|
||||
.ToArray();
|
||||
|
||||
return assets;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b259f0c39cff4c16a0d6aa27f0286f0b
|
||||
timeCreated: 1733473579
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/AssetLoader.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,36 @@
|
||||
namespace CharacterCustomizationTool.Editor
|
||||
{
|
||||
public static class AssetsPath
|
||||
{
|
||||
public const string PackageName = "Creative_Characters_FREE";
|
||||
|
||||
public static string AnimationController => _root + "Animations/Animation_Controllers/Character_Movement.controller";
|
||||
public static string SavedCharacters => _root + "Saved_Characters/";
|
||||
public static string SlotLibrary => _root + "Configs/SlotLibrary.asset";
|
||||
|
||||
private static string _root = "Assets/ithappy/" + PackageName + "/";
|
||||
|
||||
public static void SetRoot(string root)
|
||||
{
|
||||
_root = root;
|
||||
}
|
||||
|
||||
public static class BaseMesh
|
||||
{
|
||||
public static readonly string[] Keywords =
|
||||
{
|
||||
"Base",
|
||||
"Basic"
|
||||
};
|
||||
|
||||
public static string Path => _root + "Meshes/";
|
||||
}
|
||||
|
||||
public static class Folder
|
||||
{
|
||||
public static string Materials => _root + "Materials/";
|
||||
public static string Meshes => _root + "Meshes";
|
||||
public static string Faces => _root + "Meshes/Faces/";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2c2e9af7f6a4a1f957a9b57889e19c9
|
||||
timeCreated: 1712417480
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/AssetsPath.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82adddc3dfd448ad99ece633e5e75695
|
||||
timeCreated: 1735290032
|
||||
@@ -0,0 +1,194 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CharacterCustomizationTool.Editor.MaterialManagement;
|
||||
using CharacterCustomizationTool.Editor.Randomizer;
|
||||
using CharacterCustomizationTool.Editor.SlotValidation;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public class CustomizableCharacter
|
||||
{
|
||||
private static readonly SlotType[] AlwaysEnabledParts = { SlotType.Body, SlotType.Faces };
|
||||
|
||||
private readonly List<List<SavedSlot>> _savedCombinations = new();
|
||||
private readonly GameObject _characterGameObject;
|
||||
private readonly SlotValidator _slotValidator = new();
|
||||
|
||||
public SlotBase[] Slots { get; }
|
||||
public int SavedCombinationsCount => _savedCombinations.Count;
|
||||
|
||||
public CustomizableCharacter(SlotLibrary slotLibrary)
|
||||
{
|
||||
_characterGameObject = LoadBaseMesh();
|
||||
Slots = CreateSlots(slotLibrary);
|
||||
}
|
||||
|
||||
public GameObject InstantiateCharacter()
|
||||
{
|
||||
var character = Object.Instantiate(_characterGameObject, Vector3.zero, Quaternion.identity);
|
||||
|
||||
return character;
|
||||
}
|
||||
|
||||
public void SelectPrevious(SlotType slotType)
|
||||
{
|
||||
GetSlotBy(slotType).SelectPrevious();
|
||||
}
|
||||
|
||||
public void SelectNext(SlotType slotType)
|
||||
{
|
||||
GetSlotBy(slotType).SelectNext();
|
||||
}
|
||||
|
||||
public bool IsToggled(SlotType slotType)
|
||||
{
|
||||
return GetSlotBy(slotType).IsEnabled;
|
||||
}
|
||||
|
||||
public void Toggle(SlotType type, bool isToggled)
|
||||
{
|
||||
GetSlotBy(type).Toggle(isToggled);
|
||||
_slotValidator.Validate(this, type, isToggled);
|
||||
}
|
||||
|
||||
public void Draw(int previewLayer, Camera camera)
|
||||
{
|
||||
var materialProvider = new MaterialProvider();
|
||||
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
slot.Draw(materialProvider.MainColor, previewLayer, camera, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void Randomize()
|
||||
{
|
||||
var randomCharacterGenerator = new RandomCharacterGenerator();
|
||||
randomCharacterGenerator.Randomize(this);
|
||||
}
|
||||
|
||||
public void SaveCombination()
|
||||
{
|
||||
var savedCombinations = Slots.Select(slot => new SavedSlot(slot.Type, slot.IsEnabled, slot.SelectedIndex)).ToList();
|
||||
_savedCombinations.Add(savedCombinations);
|
||||
|
||||
while (_savedCombinations.Count > 4)
|
||||
{
|
||||
_savedCombinations.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void LastCombination()
|
||||
{
|
||||
var lastSavedCombination = _savedCombinations.Last();
|
||||
if (IsSame())
|
||||
{
|
||||
_savedCombinations.Remove(lastSavedCombination);
|
||||
lastSavedCombination = _savedCombinations.Last();
|
||||
}
|
||||
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
var savedCombination = lastSavedCombination.Find(c => c.SlotType == slot.Type);
|
||||
|
||||
slot.Toggle(savedCombination.IsEnabled);
|
||||
slot.Select(savedCombination.VariantIndex);
|
||||
}
|
||||
|
||||
_savedCombinations.Remove(lastSavedCombination);
|
||||
}
|
||||
|
||||
public bool IsSame()
|
||||
{
|
||||
var lastSavedCombination = _savedCombinations.Last();
|
||||
|
||||
return !Slots
|
||||
.Select(slot => new { slot, savedCombination = lastSavedCombination.Find(c => c.SlotType == slot.Type) })
|
||||
.Where(t => t.slot.IsEnabled != t.savedCombination.IsEnabled || t.slot.SelectedIndex != t.savedCombination.VariantIndex)
|
||||
.Select(t => t.slot)
|
||||
.Any();
|
||||
}
|
||||
|
||||
public void PickGroup(GroupType groupType, int index, bool isEnabled)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
if (slot.TryPickInGroup(groupType, index, isEnabled))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GetVariantsCountInGroup(GroupType groupType)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
if (slot.TryGetVariantsCountInGroup(groupType, out var count))
|
||||
{
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void ToDefault()
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
if (slot.Type != SlotType.Body && slot.Type != SlotType.Faces)
|
||||
{
|
||||
slot.Toggle(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<SlotName> GetSlotNames()
|
||||
{
|
||||
var partNames = _characterGameObject.transform
|
||||
.Cast<Transform>()
|
||||
.Where(mesh => mesh.TryGetComponent<Renderer>(out _))
|
||||
.Select(mesh => new SlotName(mesh.name)).ToList();
|
||||
|
||||
return partNames;
|
||||
}
|
||||
|
||||
public static bool IsAlwaysEnabled(SlotType slotType)
|
||||
{
|
||||
return AlwaysEnabledParts.Contains(slotType);
|
||||
}
|
||||
|
||||
private SlotBase GetSlotBy(SlotType slotType)
|
||||
{
|
||||
return Slots.FirstOrDefault(s => s.Type == slotType);
|
||||
}
|
||||
|
||||
private static GameObject LoadBaseMesh()
|
||||
{
|
||||
var availableBaseMeshes = new List<GameObject>();
|
||||
|
||||
foreach (var keyword in AssetsPath.BaseMesh.Keywords)
|
||||
{
|
||||
var baseMeshes = AssetLoader.LoadAssets<GameObject>(keyword, AssetsPath.BaseMesh.Path);
|
||||
availableBaseMeshes.AddRange(baseMeshes);
|
||||
}
|
||||
|
||||
var baseMesh = availableBaseMeshes.First();
|
||||
|
||||
return baseMesh;
|
||||
}
|
||||
|
||||
private static SlotBase[] CreateSlots(SlotLibrary slotLibrary)
|
||||
{
|
||||
var list = new List<SlotBase>();
|
||||
list.Add(new FullBodySlot(slotLibrary.FullBodyCostumes));
|
||||
list.AddRange(slotLibrary.Slots.Select(s => new Slot(s.Type, s.Groups)));
|
||||
|
||||
var sortedSlots = SlotSorter.Sort(list);
|
||||
|
||||
return sortedSlots.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb14e4484b804470a44337b79a7e352d
|
||||
timeCreated: 1735056168
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/CustomizableCharacter.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,73 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public class FullBodySlot : SlotBase
|
||||
{
|
||||
private readonly List<FullBodyVariant> _variants;
|
||||
|
||||
private FullBodyVariant _selected;
|
||||
|
||||
public override string Name => "Full Body";
|
||||
public override GameObject Preview => _selected.PreviewObject;
|
||||
public override int SelectedIndex => _variants.FindIndex(v => v.Name == _selected.Name);
|
||||
public override int VariantsCount => _variants.Count;
|
||||
public override (SlotType, Mesh)[] Meshes => _selected.Elements.Select(e => (e.Type, e.Mesh)).ToArray();
|
||||
|
||||
public FullBodySlot(FullBodyEntry[] fullBodyEntries) : base(SlotType.FullBody)
|
||||
{
|
||||
_variants = fullBodyEntries.Select(e => new FullBodyVariant(e)).ToList();
|
||||
_selected = _variants.First();
|
||||
}
|
||||
|
||||
public override void SelectNext()
|
||||
{
|
||||
_selected = _variants[GetNextIndex()];
|
||||
}
|
||||
|
||||
public override void SelectPrevious()
|
||||
{
|
||||
_selected = _variants[GetPreviousIndex()];
|
||||
}
|
||||
|
||||
public override void Select(int index)
|
||||
{
|
||||
_selected = _variants[index];
|
||||
}
|
||||
|
||||
public override bool TryGetVariantsCountInGroup(GroupType groupType, out int count)
|
||||
{
|
||||
if (groupType == GroupType.Costumes)
|
||||
{
|
||||
count = _variants.Count;
|
||||
return true;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryPickInGroup(GroupType groupType, int index, bool isEnabled)
|
||||
{
|
||||
if (!isEnabled || groupType != GroupType.Costumes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_selected = _variants[index];
|
||||
Toggle(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void DrawSlot(Material material, int previewLayer, Camera camera, int submeshIndex)
|
||||
{
|
||||
foreach (var element in _selected.Elements)
|
||||
{
|
||||
DrawMesh(element.Mesh, material, previewLayer, camera, submeshIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8adf98cee48f47c099edca891fba555f
|
||||
timeCreated: 1735290043
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/FullBodySlot.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public class FullBodyVariant
|
||||
{
|
||||
public FullBodyElement[] Elements { get; }
|
||||
public GameObject PreviewObject { get; }
|
||||
public string Name => Elements.First().Mesh.name;
|
||||
|
||||
public FullBodyVariant(FullBodyEntry fullBodyEntry)
|
||||
{
|
||||
Elements = fullBodyEntry.Slots.Select(s => new FullBodyElement(s.Type, s.GameObject.GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh)).ToArray();
|
||||
PreviewObject = PreviewCreator.CreateVariantPreview(GetPreviewMesh(Elements));
|
||||
}
|
||||
|
||||
private static Mesh GetPreviewMesh(FullBodyElement[] elements)
|
||||
{
|
||||
var element = elements.FirstOrDefault(e => e.Type == SlotType.Hat)
|
||||
?? elements.FirstOrDefault(e => e.Type == SlotType.Outerwear)
|
||||
?? elements.First();
|
||||
|
||||
return element.Mesh;
|
||||
}
|
||||
}
|
||||
|
||||
public class FullBodyElement
|
||||
{
|
||||
public SlotType Type { get; }
|
||||
public Mesh Mesh { get; }
|
||||
|
||||
public FullBodyElement(SlotType type, Mesh mesh)
|
||||
{
|
||||
Type = type;
|
||||
Mesh = mesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5936af340a884d9987333809fb1f3c4c
|
||||
timeCreated: 1735290262
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/FullBodyVariant.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,24 @@
|
||||
using CharacterCustomizationTool.Editor.MaterialManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public static class PreviewCreator
|
||||
{
|
||||
private static readonly MaterialProvider MaterialProvider = new();
|
||||
|
||||
public static GameObject CreateVariantPreview(Mesh mesh)
|
||||
{
|
||||
var variant = new GameObject(mesh.name);
|
||||
|
||||
variant.AddComponent<MeshFilter>().sharedMesh = mesh;
|
||||
variant.transform.position = Vector3.one * int.MaxValue;
|
||||
variant.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
var renderer = variant.AddComponent<MeshRenderer>();
|
||||
renderer.sharedMaterial = MaterialProvider.MainColor;
|
||||
|
||||
return variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8556696d659d49f28660a23959766758
|
||||
timeCreated: 1735298241
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/PreviewCreator.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public class Slot : SlotBase
|
||||
{
|
||||
private readonly SlotGroup[] _groups;
|
||||
private readonly List<SlotVariant> _variants;
|
||||
|
||||
private SlotVariant _selected;
|
||||
|
||||
public override string Name => Type.ToString();
|
||||
public override GameObject Preview => _selected.PreviewObject;
|
||||
public override int SelectedIndex => _variants.FindIndex(v => v.Name == _selected.Name);
|
||||
public override int VariantsCount => _variants.Count;
|
||||
|
||||
public override (SlotType, Mesh)[] Meshes => new[]
|
||||
{
|
||||
(Type, _selected.Mesh),
|
||||
};
|
||||
|
||||
public Slot(SlotType type, SlotGroupEntry[] slotGroupEntries) : base(type)
|
||||
{
|
||||
_groups = slotGroupEntries.Select(TranslateGroup).ToArray();
|
||||
_variants = FlattenVariants(_groups);
|
||||
_selected = _variants.First();
|
||||
}
|
||||
|
||||
public override void SelectNext()
|
||||
{
|
||||
_selected = _variants[GetNextIndex()];
|
||||
}
|
||||
|
||||
public override void SelectPrevious()
|
||||
{
|
||||
_selected = _variants[GetPreviousIndex()];
|
||||
}
|
||||
|
||||
public override void Select(int index)
|
||||
{
|
||||
_selected = _variants[index];
|
||||
}
|
||||
|
||||
public override bool TryGetVariantsCountInGroup(GroupType stepGroupType, out int count)
|
||||
{
|
||||
var group = _groups.FirstOrDefault(g => g.Type == stepGroupType);
|
||||
if (group != null)
|
||||
{
|
||||
count = group.Variants.Length;
|
||||
return true;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TryPickInGroup(GroupType groupType, int index, bool isEnabled)
|
||||
{
|
||||
if (!isEnabled || _groups.All(g => g.Type != groupType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var mesh = _groups.First(g => g.Type == groupType).Variants[index].Mesh;
|
||||
_selected = new SlotVariant(mesh);
|
||||
Toggle(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void DrawSlot(Material material, int previewLayer, Camera camera, int submeshIndex)
|
||||
{
|
||||
DrawMesh(_selected.Mesh, material, previewLayer, camera, submeshIndex);
|
||||
}
|
||||
|
||||
private static SlotGroup TranslateGroup(SlotGroupEntry entry)
|
||||
{
|
||||
var variants = entry.Variants
|
||||
.Select(v => new SlotVariant(v.gameObject.GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh))
|
||||
.ToArray();
|
||||
|
||||
return new SlotGroup(entry.Type, variants);
|
||||
}
|
||||
|
||||
private static List<SlotVariant> FlattenVariants(SlotGroup[] groups)
|
||||
{
|
||||
var variants = new List<SlotVariant>();
|
||||
foreach (var group in groups)
|
||||
{
|
||||
variants.AddRange(group.Variants);
|
||||
}
|
||||
|
||||
return variants;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7be4a90f04ae0554bb98e8ad42eec182
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/Slot.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,73 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public abstract class SlotBase
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
public abstract GameObject Preview { get; }
|
||||
public abstract int SelectedIndex { get; }
|
||||
public abstract int VariantsCount { get; }
|
||||
public abstract (SlotType, Mesh)[] Meshes { get; }
|
||||
|
||||
public SlotType Type { get; }
|
||||
public bool IsEnabled { get; private set; } = true;
|
||||
|
||||
protected SlotBase(SlotType type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public abstract void SelectNext();
|
||||
public abstract void SelectPrevious();
|
||||
public abstract void Select(int index);
|
||||
public abstract bool TryGetVariantsCountInGroup(GroupType groupType, out int count);
|
||||
public abstract bool TryPickInGroup(GroupType groupType, int index, bool isEnabled);
|
||||
|
||||
public void Draw(Material material, int previewLayer, Camera camera, int submeshIndex)
|
||||
{
|
||||
if (IsEnabled)
|
||||
{
|
||||
DrawSlot(material, previewLayer, camera, submeshIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOfType(SlotType type)
|
||||
{
|
||||
return Type == type;
|
||||
}
|
||||
|
||||
public void Toggle(bool isToggled)
|
||||
{
|
||||
IsEnabled = isToggled;
|
||||
}
|
||||
|
||||
protected abstract void DrawSlot(Material material, int previewLayer, Camera camera, int submeshIndex);
|
||||
|
||||
protected int GetNextIndex()
|
||||
{
|
||||
var targetIndex = SelectedIndex + 1;
|
||||
if (targetIndex >= VariantsCount)
|
||||
{
|
||||
targetIndex = 0;
|
||||
}
|
||||
|
||||
return targetIndex;
|
||||
}
|
||||
|
||||
protected int GetPreviousIndex()
|
||||
{
|
||||
var targetIndex = SelectedIndex - 1;
|
||||
if (targetIndex < 0)
|
||||
{
|
||||
targetIndex = VariantsCount - 1;
|
||||
}
|
||||
return targetIndex;
|
||||
}
|
||||
|
||||
protected static void DrawMesh(Mesh mesh, Material material, int previewLayer, Camera camera, int submeshIndex)
|
||||
{
|
||||
Graphics.DrawMesh(mesh, new Vector3(0, -.01f, 0), Quaternion.identity, material, previewLayer, camera, submeshIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4790fea957a0452c9b3fdafae8c50a85
|
||||
timeCreated: 1735299299
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/SlotBase.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public class SlotGroup
|
||||
{
|
||||
public readonly GroupType Type;
|
||||
public readonly SlotVariant[] Variants;
|
||||
|
||||
public SlotGroup(GroupType type, SlotVariant[] variants)
|
||||
{
|
||||
Type = type;
|
||||
Variants = variants;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8574b612b164d90a75a3fe20a376234
|
||||
timeCreated: 1735291905
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/SlotGroup.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public static class SlotLibraryLoader
|
||||
{
|
||||
public static SlotLibrary LoadSlotLibrary()
|
||||
{
|
||||
return AssetDatabase.LoadAssetAtPath<SlotLibrary>(AssetsPath.SlotLibrary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c3cb4b19185480caba797a0824231a7
|
||||
timeCreated: 1735291150
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/SlotLibraryLoader.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Character
|
||||
{
|
||||
public class SlotVariant
|
||||
{
|
||||
public Mesh Mesh { get; }
|
||||
public GameObject PreviewObject { get; }
|
||||
public string Name => Mesh.name;
|
||||
|
||||
public SlotVariant(Mesh mesh)
|
||||
{
|
||||
Mesh = mesh;
|
||||
PreviewObject = PreviewCreator.CreateVariantPreview(mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cea17fb1a249944b8f64f0a431b340d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Character/SlotVariant.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,253 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using CharacterCustomizationTool.Editor.Character;
|
||||
using CharacterCustomizationTool.Editor.FaceEditor;
|
||||
using CharacterCustomizationTool.Editor.MaterialManagement;
|
||||
using Controller;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Animations;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor
|
||||
{
|
||||
public class CharacterCustomizationWindow : EditorWindow
|
||||
{
|
||||
private const string PreviewLayerName = "Character Preview";
|
||||
|
||||
private CustomizableCharacter _customizableCharacter;
|
||||
private PartsEditor _partsEditor;
|
||||
private Camera _camera;
|
||||
private int _previewLayer;
|
||||
private RenderTexture _renderTexture;
|
||||
private string _prefabPath;
|
||||
|
||||
[MenuItem("Tools/Character Customization")]
|
||||
private static void Init()
|
||||
{
|
||||
FindRoot();
|
||||
var window = GetWindow<CharacterCustomizationWindow>("Character Customization");
|
||||
window.minSize = new Vector2(990, 655);
|
||||
window.Show();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_customizableCharacter = new CustomizableCharacter(SlotLibraryLoader.LoadSlotLibrary());
|
||||
_partsEditor = new PartsEditor();
|
||||
|
||||
LayerMaskUtility.CreateLayer(PreviewLayerName);
|
||||
_previewLayer = LayerMask.NameToLayer(PreviewLayerName);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
var rect = new Rect(10, 10, 300, 300);
|
||||
|
||||
CreateRenderTexture();
|
||||
InitializeCamera();
|
||||
DrawCharacter();
|
||||
_partsEditor.OnGUI(new Rect(330, 10, position.width - 330, position.height), _customizableCharacter);
|
||||
|
||||
GUI.DrawTexture(rect, _renderTexture, ScaleMode.StretchToFill, false);
|
||||
|
||||
GUI.Label(new Rect(10, 320, 100, 25), "Prefab folder:");
|
||||
GUI.Label(new Rect(10, 345, 350, 25), AssetsPath.SavedCharacters);
|
||||
_prefabPath = GUI.TextField(new Rect(10, 372, 300, 20), _prefabPath);
|
||||
|
||||
var saveButtonRect = new Rect(10, 400, 300, 40);
|
||||
if (GUI.Button(saveButtonRect, "Save Prefab"))
|
||||
{
|
||||
SavePrefab();
|
||||
}
|
||||
|
||||
var randomizeButtonRect = new Rect(85, 450, 150, 30);
|
||||
if (GUI.Button(randomizeButtonRect, "Randomize"))
|
||||
{
|
||||
Randomize();
|
||||
}
|
||||
|
||||
var isZero = _customizableCharacter.SavedCombinationsCount == 0;
|
||||
var isSame = false;
|
||||
var lessThenTwo = false;
|
||||
|
||||
if (!isZero)
|
||||
{
|
||||
isSame = _customizableCharacter.IsSame();
|
||||
lessThenTwo = _customizableCharacter.SavedCombinationsCount < 2;
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledScope(isZero || (isSame && lessThenTwo)))
|
||||
{
|
||||
var lastButtonRect = new Rect(240, 450, 50, 30);
|
||||
if (GUI.Button(lastButtonRect, "Last"))
|
||||
{
|
||||
_customizableCharacter.LastCombination();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SavePrefab()
|
||||
{
|
||||
var character = _customizableCharacter.InstantiateCharacter();
|
||||
var materialProvider = new MaterialProvider();
|
||||
|
||||
var enabledSlots = _customizableCharacter.Slots.Where(s => s.IsEnabled).ToArray();
|
||||
|
||||
foreach (var slot in enabledSlots)
|
||||
{
|
||||
foreach (var mesh in slot.Meshes)
|
||||
{
|
||||
var child = character.transform.Cast<Transform>().First(t => t.name.StartsWith(mesh.Item1.ToString()));
|
||||
if (child.TryGetComponent<SkinnedMeshRenderer>(out var skinnedMeshRenderer))
|
||||
{
|
||||
skinnedMeshRenderer.sharedMesh = mesh.Item2;
|
||||
skinnedMeshRenderer.sharedMaterial = materialProvider.MainColor;
|
||||
skinnedMeshRenderer.localBounds = skinnedMeshRenderer.sharedMesh.bounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FaceLoader.AddFaces(character);
|
||||
AddAnimator(character);
|
||||
AddMovementComponents(character);
|
||||
|
||||
var prefabPath = AssetsPath.SavedCharacters + _prefabPath;
|
||||
Directory.CreateDirectory(prefabPath);
|
||||
var path = AssetDatabase.GenerateUniqueAssetPath($"{prefabPath}/Character.prefab");
|
||||
PrefabUtility.SaveAsPrefabAsset(character, path);
|
||||
DestroyImmediate(character);
|
||||
}
|
||||
|
||||
private static void AddAnimator(GameObject character)
|
||||
{
|
||||
var controller = AssetDatabase.LoadAssetAtPath<AnimatorController>(AssetsPath.AnimationController);
|
||||
var animator = character.GetComponent<Animator>();
|
||||
animator.runtimeAnimatorController = controller;
|
||||
animator.applyRootMotion = false;
|
||||
}
|
||||
|
||||
private static void AddMovementComponents(GameObject character)
|
||||
{
|
||||
AddCharacterController(character);
|
||||
character.AddComponent<CharacterMover>();
|
||||
character.AddComponent<MovePlayerInput>();
|
||||
}
|
||||
|
||||
private static void AddCharacterController(GameObject character)
|
||||
{
|
||||
var characterController = character.AddComponent<CharacterController>();
|
||||
|
||||
characterController.center = new Vector3(0, .95f, 0);
|
||||
characterController.radius = .4f;
|
||||
characterController.height = 1.8f;
|
||||
}
|
||||
|
||||
private void Randomize()
|
||||
{
|
||||
_customizableCharacter.Randomize();
|
||||
_customizableCharacter.SaveCombination();
|
||||
}
|
||||
|
||||
private void InitializeCamera()
|
||||
{
|
||||
if (_camera)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var cameraPivot = new GameObject("CameraPivot").transform;
|
||||
cameraPivot.gameObject.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
var cameraObject = new GameObject("PreviewCamera")
|
||||
{
|
||||
hideFlags = HideFlags.HideAndDontSave
|
||||
};
|
||||
|
||||
_camera = cameraObject.AddComponent<Camera>();
|
||||
_camera.targetTexture = _renderTexture;
|
||||
_camera.clearFlags = CameraClearFlags.SolidColor;
|
||||
_camera.renderingPath = RenderingPath.Forward;
|
||||
_camera.enabled = false;
|
||||
_camera.useOcclusionCulling = false;
|
||||
_camera.cameraType = CameraType.Preview;
|
||||
_camera.fieldOfView = 4.5f;
|
||||
_camera.clearFlags = CameraClearFlags.SolidColor;
|
||||
_camera.transform.SetParent(cameraPivot);
|
||||
_camera.cullingMask = 1 << _previewLayer;
|
||||
|
||||
cameraPivot.Rotate(Vector3.up, 150, Space.Self);
|
||||
}
|
||||
|
||||
private void CreateRenderTexture()
|
||||
{
|
||||
if (_renderTexture)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_renderTexture = new RenderTexture(300, 300, 30, RenderTextureFormat.ARGB32)
|
||||
{
|
||||
antiAliasing = 1
|
||||
};
|
||||
}
|
||||
|
||||
private void DrawCharacter()
|
||||
{
|
||||
_camera.transform.localPosition = new Vector3(0, 1.1f, -36);
|
||||
_customizableCharacter.Draw(_previewLayer, _camera);
|
||||
_camera.Render();
|
||||
}
|
||||
|
||||
private static void FindRoot()
|
||||
{
|
||||
var anchorAssetGuid = string.Empty;
|
||||
|
||||
foreach (var keyword in AssetsPath.BaseMesh.Keywords)
|
||||
{
|
||||
var assetGuids = AssetDatabase.FindAssets(keyword);
|
||||
|
||||
foreach (var guid in assetGuids)
|
||||
{
|
||||
if (AssetDatabase.GUIDToAssetPath(guid).Contains("Meshes"))
|
||||
{
|
||||
anchorAssetGuid = guid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(anchorAssetGuid))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var anchorAssetPath = AssetDatabase.GUIDToAssetPath(anchorAssetGuid);
|
||||
var pathParts = anchorAssetPath.Split('/');
|
||||
var packTitleParts = AssetsPath.PackageName.Split('_');
|
||||
var rootFound = false;
|
||||
for (var i = pathParts.Length - 1; i >= 0; i--)
|
||||
{
|
||||
if (rootFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var part in packTitleParts)
|
||||
{
|
||||
rootFound = false;
|
||||
|
||||
if (!pathParts[i].Contains(part))
|
||||
{
|
||||
pathParts[i] = string.Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
rootFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
var root = string.Join("/", pathParts.Where(p => !string.IsNullOrEmpty(p)).ToArray()) + "/";
|
||||
AssetsPath.SetRoot(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09a7b34151da87d46a6e0cff3b379e11
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/CharacterCustomizationWindow.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf7c23847d84410d81a5e3b60afd39cf
|
||||
timeCreated: 1733473101
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CharacterCustomizationTool.FaceManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.FaceEditor
|
||||
{
|
||||
public static class FaceLoader
|
||||
{
|
||||
public static void AddFaces(GameObject gameObject)
|
||||
{
|
||||
var faceMeshes = AssetLoader.LoadAssets<Mesh>("t:Mesh", AssetsPath.Folder.Faces).ToArray();
|
||||
var maleFace = FilterBy("Male", faceMeshes);
|
||||
var femaleFace = FilterBy("Female", faceMeshes);
|
||||
|
||||
var groupedMaleFaces = Group(maleFace);
|
||||
var groupedFemaleFaces = Group(femaleFace);
|
||||
|
||||
var skinnedMeshRenderer = gameObject.transform
|
||||
.Cast<Transform>()
|
||||
.First(t => t.name.StartsWith("Face"))
|
||||
.GetComponent<SkinnedMeshRenderer>();
|
||||
|
||||
if (skinnedMeshRenderer.sharedMesh)
|
||||
{
|
||||
var facePicker = gameObject.AddComponent<FacePicker>();
|
||||
|
||||
var nameSections = skinnedMeshRenderer.sharedMesh.name.Split("_");
|
||||
var groupedFaces = nameSections.First() == "Male" ? groupedMaleFaces : groupedFemaleFaces;
|
||||
var faces = ChooseFaces(skinnedMeshRenderer.sharedMesh.name, groupedFaces);
|
||||
|
||||
facePicker.SetFaces(faces);
|
||||
}
|
||||
}
|
||||
|
||||
private static Mesh[] ChooseFaces(string faceName, Dictionary<string, Mesh[]> groupedFaces)
|
||||
{
|
||||
var faceKey = faceName.Split("_")[3];
|
||||
var faces = groupedFaces[faceKey];
|
||||
|
||||
return faces;
|
||||
}
|
||||
|
||||
private static IEnumerable<Mesh> FilterBy(string keyword, IEnumerable<Mesh> meshes)
|
||||
{
|
||||
return meshes.Where(m => m.name.StartsWith(keyword)).ToArray();
|
||||
}
|
||||
|
||||
private static Dictionary<string, Mesh[]> Group(IEnumerable<Mesh> meshes)
|
||||
{
|
||||
var groupedMeshes = meshes
|
||||
.GroupBy(m => m.name.Split("_")[3])
|
||||
.ToDictionary(g => g.Key, g => g.ToArray());
|
||||
|
||||
return groupedMeshes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c4ca2ceb1694e368fdc48fb95737e0d
|
||||
timeCreated: 1733473111
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/FaceEditor/FaceLoader.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using CharacterCustomizationTool.FaceManagement;
|
||||
using UnityEditor;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.FaceEditor
|
||||
{
|
||||
[CustomEditor(typeof(FacePicker))]
|
||||
public class FacePickerEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
var facePicker = (FacePicker)target;
|
||||
|
||||
var previousFace = facePicker.ActiveFace;
|
||||
|
||||
var availableFaces =
|
||||
Enum.GetValues(typeof(FaceType))
|
||||
.Cast<FaceType>()
|
||||
.Where(facePicker.HasFace)
|
||||
.ToArray();
|
||||
|
||||
var activeFaceIndex = Array.IndexOf(availableFaces, facePicker.ActiveFace);
|
||||
|
||||
var newFaceIndex = EditorGUILayout.Popup("Face", activeFaceIndex, availableFaces.Select(f => f.ToString()).ToArray());
|
||||
var newFace = availableFaces[newFaceIndex];
|
||||
|
||||
if (newFace != previousFace)
|
||||
{
|
||||
facePicker.PickFace(newFace);
|
||||
|
||||
EditorUtility.SetDirty(facePicker.gameObject);
|
||||
AssetDatabase.SaveAssetIfDirty(facePicker.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d12dd8e2ab416fc47b32a9c0579cfb40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/FaceEditor/FacePickerEditor.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace CharacterCustomizationTool.Editor
|
||||
{
|
||||
public enum GroupType
|
||||
{
|
||||
Body,
|
||||
Costumes,
|
||||
FaceAccessories,
|
||||
Faces,
|
||||
Glasses,
|
||||
Gloves,
|
||||
Hairstyle,
|
||||
HairstyleSingle,
|
||||
Hat,
|
||||
HatSingle,
|
||||
Mascots,
|
||||
Outfit,
|
||||
Outwear,
|
||||
Pants,
|
||||
Shoes,
|
||||
Shorts,
|
||||
Socks,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b59a73d0010b514bb4dc68df2e34a23
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/GroupType.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor
|
||||
{
|
||||
public class LayerMaskUtility
|
||||
{
|
||||
public static void CreateLayer(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name), "New layer name string is either null or empty.");
|
||||
}
|
||||
|
||||
var tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
|
||||
var layerProps = tagManager.FindProperty("layers");
|
||||
var propCount = layerProps.arraySize;
|
||||
|
||||
SerializedProperty firstEmptyProp = null;
|
||||
|
||||
for (var i = 0; i < propCount; i++)
|
||||
{
|
||||
var layerProp = layerProps.GetArrayElementAtIndex(i);
|
||||
var stringValue = layerProp.stringValue;
|
||||
if (stringValue == name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (i < 8 || stringValue != string.Empty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
firstEmptyProp ??= layerProp;
|
||||
}
|
||||
|
||||
if (firstEmptyProp == null)
|
||||
{
|
||||
Debug.LogError("Maximum limit of " + propCount + " layers exceeded. Layer \"" + name + "\" not created.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
firstEmptyProp.stringValue = name;
|
||||
tagManager.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 496fab0852c0452fad73654ac2a8306d
|
||||
timeCreated: 1737047512
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/LayerMaskUtility.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0bf47c2abc5e479abe7e9c7250f2f869
|
||||
timeCreated: 1733383645
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.MaterialManagement
|
||||
{
|
||||
public class MaterialOnDemand
|
||||
{
|
||||
private readonly string[] _paths;
|
||||
|
||||
private Material _value;
|
||||
|
||||
public Material Value => _value ? _value : LoadMaterial();
|
||||
|
||||
public MaterialOnDemand(params string[] paths)
|
||||
{
|
||||
_paths = paths;
|
||||
}
|
||||
|
||||
private Material LoadMaterial()
|
||||
{
|
||||
foreach (var path in _paths)
|
||||
{
|
||||
var loadedMaterial = AssetDatabase.LoadAssetAtPath<Material>(path);
|
||||
|
||||
if (loadedMaterial != null)
|
||||
{
|
||||
return loadedMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64d9492e12b140e5a5d41e01cd21f244
|
||||
timeCreated: 1733383656
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/MaterialManagement/MaterialOnDemand.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,20 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.MaterialManagement
|
||||
{
|
||||
public static class MaterialPaths
|
||||
{
|
||||
private static readonly string[] MainColorNames = { "Material", "Color" };
|
||||
private static readonly string GlassName = "Glass";
|
||||
private static readonly string EmissionName = "Emission";
|
||||
|
||||
public static readonly string[] MainColorPaths = MainColorNames.Select(GetMaterialPath).ToArray();
|
||||
public static readonly string GlassPath = GetMaterialPath(GlassName);
|
||||
public static readonly string EmissionPath = GetMaterialPath(EmissionName);
|
||||
|
||||
private static string GetMaterialPath(string materialName)
|
||||
{
|
||||
return $"{AssetsPath.Folder.Materials}{materialName}.mat";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcdec3d40fc84864a9f14ccc7367a694
|
||||
timeCreated: 1733383685
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/MaterialManagement/MaterialPaths.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.MaterialManagement
|
||||
{
|
||||
public class MaterialProvider
|
||||
{
|
||||
private readonly MaterialOnDemand _mainColor = new(MaterialPaths.MainColorPaths);
|
||||
private readonly MaterialOnDemand _glass = new(MaterialPaths.GlassPath);
|
||||
private readonly MaterialOnDemand _emission = new(MaterialPaths.EmissionPath);
|
||||
|
||||
public Material MainColor => _mainColor.Value;
|
||||
public Material Glass => _glass.Value;
|
||||
public Material Emission => _emission.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 706da59b74ca42979c0359ece9905274
|
||||
timeCreated: 1733381019
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/MaterialManagement/MaterialProvider.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,118 @@
|
||||
using CharacterCustomizationTool.Editor.Character;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor
|
||||
{
|
||||
public class PartsEditor
|
||||
{
|
||||
private const float Width = 150;
|
||||
|
||||
private Vector2 _scrollPosition;
|
||||
|
||||
public void OnGUI(Rect rect, CustomizableCharacter character)
|
||||
{
|
||||
var slots = character.Slots;
|
||||
using (new GUI.GroupScope(rect))
|
||||
{
|
||||
using (var scrollViewScope = new GUILayout.ScrollViewScope(_scrollPosition))
|
||||
{
|
||||
_scrollPosition = scrollViewScope.scrollPosition;
|
||||
using (new GUILayout.HorizontalScope())
|
||||
{
|
||||
const int step = 3;
|
||||
var index = 0;
|
||||
while (index < slots.Length)
|
||||
{
|
||||
using (new GUILayout.VerticalScope(GUILayout.Width(100)))
|
||||
{
|
||||
for (var i = index; i < index + step; i++)
|
||||
{
|
||||
if (i < slots.Length)
|
||||
{
|
||||
RenderPart(character, slots[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
index += step;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderPart(CustomizableCharacter character, SlotBase slot)
|
||||
{
|
||||
using (new GUILayout.VerticalScope(EditorStyles.helpBox, GUILayout.Width(Width)))
|
||||
{
|
||||
GUILayout.Label(slot.Name);
|
||||
GUILayout.Box(AssetPreview.GetAssetPreview(slot.Preview));
|
||||
if (CustomizableCharacter.IsAlwaysEnabled(slot.Type))
|
||||
{
|
||||
using (new EditorGUI.DisabledScope(true))
|
||||
{
|
||||
RenderToggle(character, slot.Type);
|
||||
}
|
||||
}
|
||||
else if (slot.Type == SlotType.FullBody)
|
||||
{
|
||||
RenderToggle(character, slot.Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (new EditorGUI.DisabledScope(false))
|
||||
{
|
||||
RenderToggle(character, slot.Type);
|
||||
}
|
||||
}
|
||||
|
||||
using (new EditorGUI.DisabledScope(!slot.IsEnabled))
|
||||
{
|
||||
using (new GUILayout.HorizontalScope(EditorStyles.helpBox, GUILayout.Width(Width)))
|
||||
{
|
||||
RenderLeftButton(character, slot.Type);
|
||||
RenderCounter(slot);
|
||||
RenderRightButton(character, slot.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderToggle(CustomizableCharacter character, SlotType type)
|
||||
{
|
||||
var isToggled = EditorGUILayout.ToggleLeft("Enabled", character.IsToggled(type), GUILayout.Width(100));
|
||||
character.Toggle(type, isToggled);
|
||||
}
|
||||
|
||||
private static void RenderLeftButton(CustomizableCharacter character, SlotType slotType)
|
||||
{
|
||||
if (GUILayout.Button("<"))
|
||||
{
|
||||
character.SelectPrevious(slotType);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderRightButton(CustomizableCharacter character, SlotType slotType)
|
||||
{
|
||||
if (GUILayout.Button(">"))
|
||||
{
|
||||
character.SelectNext(slotType);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RenderCounter(SlotBase slot)
|
||||
{
|
||||
var style = new GUIStyle
|
||||
{
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
normal =
|
||||
{
|
||||
textColor = Color.white
|
||||
},
|
||||
fixedWidth = 70,
|
||||
};
|
||||
|
||||
GUILayout.Label($"{slot.SelectedIndex + 1}/{slot.VariantsCount}", style);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5823a3186511e4043be688c233988ff0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/PartsEditor.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccc51c69798f84d438888c8c9eef01e8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using CharacterCustomizationTool.Editor.Character;
|
||||
using CharacterCustomizationTool.Editor.Randomizer.Steps;
|
||||
using CharacterCustomizationTool.Editor.Randomizer.Steps.Impl;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer
|
||||
{
|
||||
public class RandomCharacterGenerator
|
||||
{
|
||||
private readonly IRandomizerStep[] _randomizerSteps =
|
||||
{
|
||||
new FaceStep(),
|
||||
new BodyStep(),
|
||||
new CostumesStep(),
|
||||
new MascotsStep(),
|
||||
new OutfitStep(),
|
||||
new OutwearStep(),
|
||||
new PantsStep(),
|
||||
new ShortsStep(),
|
||||
new SocksStep(),
|
||||
new HatStep(),
|
||||
new HatSingleStep(),
|
||||
new FaceAccessoriesStep(),
|
||||
new GlassesStep(),
|
||||
new ShoesStep(),
|
||||
new HairstyleSingleStep(),
|
||||
new HairstyleStep(),
|
||||
new GlovesStep(),
|
||||
};
|
||||
|
||||
public void Randomize(CustomizableCharacter character)
|
||||
{
|
||||
character.ToDefault();
|
||||
|
||||
var groups = Enum.GetValues(typeof(GroupType)).Cast<GroupType>().ToArray();
|
||||
|
||||
foreach (var step in _randomizerSteps)
|
||||
{
|
||||
var variantsCount = character.GetVariantsCountInGroup(step.GroupType);
|
||||
|
||||
var stepResult = step.Process(variantsCount, groups);
|
||||
|
||||
groups = stepResult.AvailableGroups;
|
||||
character.PickGroup(step.GroupType, stepResult.Index, stepResult.IsActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90f894f9feef4ac9997c9a681333e648
|
||||
timeCreated: 1736350992
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/RandomCharacterGenerator.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer
|
||||
{
|
||||
public class StepResult
|
||||
{
|
||||
public int Index { get; }
|
||||
public bool IsActive { get; }
|
||||
public GroupType[] AvailableGroups { get; }
|
||||
|
||||
public StepResult(int index, bool isActive, GroupType[] availableGroups)
|
||||
{
|
||||
Index = index;
|
||||
IsActive = isActive;
|
||||
AvailableGroups = availableGroups;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd07b1e4f88a4af696f5614472c15f13
|
||||
timeCreated: 1736972446
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/StepResult.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13350f8e69d34f0ab019a0b7ce981866
|
||||
timeCreated: 1736674860
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps
|
||||
{
|
||||
public interface IRandomizerStep
|
||||
{
|
||||
GroupType GroupType { get; }
|
||||
|
||||
StepResult Process(int count, GroupType[] groups);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c471afe9dd44d074f99841183c4cf278
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/IRandomizerStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe8f5cfcc1874a58b1af97c477b086f4
|
||||
timeCreated: 1736674865
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class BodyStep : IRandomizerStep
|
||||
{
|
||||
public GroupType GroupType => GroupType.Body;
|
||||
|
||||
public StepResult Process(int count, GroupType[] groups)
|
||||
{
|
||||
var newGroups = groups.Where(g => g != GroupType.Body).ToArray();
|
||||
|
||||
return new StepResult(Random.Range(0, count), true, newGroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da95423e69334f7e96f7fe9f3db0ef5f
|
||||
timeCreated: 1736599151
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/BodyStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class CostumesStep : StepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Costumes;
|
||||
|
||||
protected override float Probability => .2f;
|
||||
|
||||
public override StepResult Process(int count, GroupType[] groups)
|
||||
{
|
||||
if (Random.value > Probability)
|
||||
{
|
||||
return new StepResult(0, false, RemoveSelf(groups));
|
||||
}
|
||||
|
||||
return new StepResult(Random.Range(0, count), true, Array.Empty<GroupType>());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1cd3103d9d741ff9aed903f55545928
|
||||
timeCreated: 1736674915
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/CostumesStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class FaceAccessoriesStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.FaceAccessories;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Glasses,
|
||||
GroupType.Shoes,
|
||||
GroupType.HairstyleSingle,
|
||||
GroupType.Hairstyle,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f44888e8146b4a57b11907b4ef3f6d22
|
||||
timeCreated: 1736681858
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/FaceAccessoriesStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class FaceStep : IRandomizerStep
|
||||
{
|
||||
public GroupType GroupType => GroupType.Faces;
|
||||
|
||||
public StepResult Process(int count, GroupType[] groups)
|
||||
{
|
||||
var newGroups = groups.Where(g => g != GroupType.Faces).ToArray();
|
||||
|
||||
return new StepResult(Random.Range(0, count), true, newGroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d3b7299fb554507b6a7aa4398dd60db
|
||||
timeCreated: 1736350792
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/FaceStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class GlassesStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Glasses;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Shoes,
|
||||
GroupType.HairstyleSingle,
|
||||
GroupType.Hairstyle,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42b88327cc4b4059a9900d7451f2b1ad
|
||||
timeCreated: 1736681911
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/GlassesStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class GlovesStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Gloves;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => Array.Empty<GroupType>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 369aa049cb934312955bdfbcbfb0cf6c
|
||||
timeCreated: 1736682133
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/GlovesStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class HairstyleSingleStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.HairstyleSingle;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4dbf3a338f2e4959976c21ad98480d91
|
||||
timeCreated: 1736682038
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/HairstyleSingleStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class HairstyleStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Hairstyle;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd5070c46d6e4eba9378623e5ab9b2b0
|
||||
timeCreated: 1736682092
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/HairstyleStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class HatSingleStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.HatSingle;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.FaceAccessories,
|
||||
GroupType.Shoes,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b225042b1974444979dbc9e3040da4a
|
||||
timeCreated: 1736681763
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/HatSingleStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class HatStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Hat;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.FaceAccessories,
|
||||
GroupType.Glasses,
|
||||
GroupType.Shoes,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 030380cece0448e394e70c7c7022f2a8
|
||||
timeCreated: 1736681665
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/HatStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class MascotsStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Mascots;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Pants,
|
||||
GroupType.Shorts,
|
||||
GroupType.FaceAccessories,
|
||||
GroupType.Glasses,
|
||||
GroupType.Shoes,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 793ebe74e68a4bf0afaa3eb68e2387c9
|
||||
timeCreated: 1736676749
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/MascotsStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class OutfitStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Outfit;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Hat,
|
||||
GroupType.HatSingle,
|
||||
GroupType.FaceAccessories,
|
||||
GroupType.Glasses,
|
||||
GroupType.Shoes,
|
||||
GroupType.HairstyleSingle,
|
||||
GroupType.Hairstyle,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9f1c016b047465b971475eddd6d9e6f
|
||||
timeCreated: 1736677982
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/OutfitStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class OutwearStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Outwear;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Pants,
|
||||
GroupType.Shorts,
|
||||
GroupType.Hat,
|
||||
GroupType.HatSingle,
|
||||
GroupType.FaceAccessories,
|
||||
GroupType.Glasses,
|
||||
GroupType.Shoes,
|
||||
GroupType.HairstyleSingle,
|
||||
GroupType.Hairstyle,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74f9991652aa46348c881d0e7908b073
|
||||
timeCreated: 1736678464
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/OutwearStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class PantsStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Pants;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Hat,
|
||||
GroupType.HatSingle,
|
||||
GroupType.FaceAccessories,
|
||||
GroupType.Glasses,
|
||||
GroupType.Shoes,
|
||||
GroupType.HairstyleSingle,
|
||||
GroupType.Hairstyle,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2967f0c46bdd4c818e3a8a951b2652a2
|
||||
timeCreated: 1736678855
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/PantsStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class ShoesStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Shoes;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.HairstyleSingle,
|
||||
GroupType.Hairstyle,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10cfdcedf32c4647a6b2f6c62d9529c4
|
||||
timeCreated: 1736681964
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/ShoesStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class ShortsStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Shorts;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Hat,
|
||||
GroupType.HatSingle,
|
||||
GroupType.FaceAccessories,
|
||||
GroupType.Glasses,
|
||||
GroupType.Shoes,
|
||||
GroupType.HairstyleSingle,
|
||||
GroupType.Hairstyle,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
|
||||
public override StepResult Process(int count, GroupType[] groups)
|
||||
{
|
||||
var cannotProcess = !groups.Contains(GroupType);
|
||||
groups = RemoveSelf(groups);
|
||||
|
||||
if (cannotProcess || Random.value > Probability)
|
||||
{
|
||||
return new StepResult(0, false, groups);
|
||||
}
|
||||
|
||||
var newGroups = groups.Where(g => CompatibleGroups.Contains(g)).ToArray();
|
||||
var finalGroups = newGroups.ToList();
|
||||
finalGroups.Add(GroupType.Socks);
|
||||
|
||||
return new StepResult(Random.Range(0, count), true, finalGroups.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b73523352e7483bbe87c1ebc732a1ff
|
||||
timeCreated: 1736679843
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/ShortsStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public abstract class SlotStepBase : StepBase, IRandomizerStep
|
||||
{
|
||||
protected abstract GroupType[] CompatibleGroups { get; }
|
||||
|
||||
public override StepResult Process(int count, GroupType[] groups)
|
||||
{
|
||||
var cannotProcess = !groups.Contains(GroupType);
|
||||
groups = RemoveSelf(groups);
|
||||
|
||||
if (cannotProcess || Random.value > Probability)
|
||||
{
|
||||
return new StepResult(0, false, groups);
|
||||
}
|
||||
|
||||
var newGroups = groups.Where(g => CompatibleGroups.Contains(g)).ToArray();
|
||||
|
||||
return new StepResult(Random.Range(0, count), true, newGroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c680eeb9d4824f80853cbb97cd228aab
|
||||
timeCreated: 1736678645
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/SlotStepBase.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public class SocksStep : SlotStepBase, IRandomizerStep
|
||||
{
|
||||
public override GroupType GroupType => GroupType.Socks;
|
||||
|
||||
protected override float Probability => .5f;
|
||||
|
||||
protected override GroupType[] CompatibleGroups => new[]
|
||||
{
|
||||
GroupType.Hat,
|
||||
GroupType.HatSingle,
|
||||
GroupType.FaceAccessories,
|
||||
GroupType.Glasses,
|
||||
GroupType.Shoes,
|
||||
GroupType.HairstyleSingle,
|
||||
GroupType.Hairstyle,
|
||||
GroupType.Gloves,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 246406a9e2694ee199d27d33b1a5abd2
|
||||
timeCreated: 1736681519
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/SocksStep.cs
|
||||
uploadId: 780839
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace CharacterCustomizationTool.Editor.Randomizer.Steps.Impl
|
||||
{
|
||||
public abstract class StepBase : IRandomizerStep
|
||||
{
|
||||
public abstract GroupType GroupType { get; }
|
||||
|
||||
protected virtual float Probability => .35f;
|
||||
|
||||
public abstract StepResult Process(int count, GroupType[] groups);
|
||||
|
||||
protected GroupType[] RemoveSelf(GroupType[] groups)
|
||||
{
|
||||
return groups.Where(g => g != GroupType).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e2f5ffd08ce455b937d13c7d07ece65
|
||||
timeCreated: 1736685991
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 304841
|
||||
packageName: Creative Characters FREE - Animated Low Poly 3D Models
|
||||
packageVersion: 2.2
|
||||
assetPath: Assets/ithappy/Creative_Characters_FREE/Scripts/Editor/Randomizer/Steps/Impl/StepBase.cs
|
||||
uploadId: 780839
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user