using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class ThirdPersonCharacter2 : UdonSharpBehaviour
{
[SerializeField] float _MovingTurnSpeed = 720;
[SerializeField] float _StationaryTurnSpeed = 720;
[SerializeField] float _MoveSpeedMultiplier = 1f;
[SerializeField] float _AnimSpeedMultiplier = 1f;
[SerializeField] private SkinnedMeshRenderer m_Face;
private Rigidbody m_Rigidbody { get { return GetComponent<Rigidbody>(); } }
private Animator m_Animator { get { return GetComponent<Animator>(); } }
const float _GroundCheckDistance = 0.2f;
float _TurnAmount;
float _ForwardAmount;
int _Nyaa;
Vector3 m_GroundNormal;
float _Mabataki_Weight;
float _pastsecm = 0.0f;
float _nextsecm = 0.0f;
float _Kuchi_Weight;
float _pastseck = 0.0f;
float _nextseck = 0.0f;
bool _mabataki_on = true;
float pastnyaatime = 0f;
float nextnyaatime = 0f;
int _nyaa_point = 0;
string _mabataki_shapeky = "blink";
string _kuchiake_shapekey = "kuchi_pokan";
string[] _nyaa1_shapekeys = new string[] { "kuchi_△_2", "kuchi_yaeba_×", "surprise", "shiitake" };
string[] _nyaa1_shapekeys_rev = new string[] { "kuchi_pokan" };
string[] _nyaa2_shapekeys = new string[] { "><", "kuchi_wa", "kuchi_smile_1" };
string[] _nyaa2_shapekeys_rev = new string[] { "kuchi_pokan" };
void Start()
{
m_Rigidbody.constraints = RigidbodyConstraints.FreezeRotation;
}
private void FixedUpdate()
{
BlendShapeRandomMabataki();
BlendShapeRandomKuchiake(_Nyaa);
}
private int s2i(string shapekeyname)
{
int idx = m_Face.sharedMesh.GetBlendShapeIndex(shapekeyname);
if (idx < 0) idx = 0;
return idx;
}
private void BlendShapeRandomMabataki()
{
if (_mabataki_on)
{
_pastsecm += Time.deltaTime;
if (_pastsecm > _nextsecm)
{
_nextsecm = Random.Range(4.0f, 7.5f);
_pastsecm = 0.0f;
}
if (_pastsecm < 0.2f)
{
if (_pastsecm < 0.1f)
{
_Mabataki_Weight += (Time.deltaTime / 0.1f) * 100f;
if (_Mabataki_Weight > 99.9f) _Mabataki_Weight = 100f;
m_Face.SetBlendShapeWeight(s2i(_mabataki_shapeky), _Mabataki_Weight);
}
else if (_pastsecm < 0.2f)
{
_Mabataki_Weight -= (Time.deltaTime / 0.1f) * 100f;
if (_Mabataki_Weight < 0.01f) _Mabataki_Weight = 0.0f;
m_Face.SetBlendShapeWeight(s2i(_mabataki_shapeky), _Mabataki_Weight);
}
}
} else
{
m_Face.SetBlendShapeWeight(s2i(_mabataki_shapeky), 0f);
}
}
private void BlendShapeRandomKuchiake(int nyaa)
{
_pastseck += Time.deltaTime;
if (nyaa != 0)
{
_nextseck = _pastseck + 5.0f;
return;
}
if (_pastseck > _nextseck)
{
_nextseck = Random.Range(10.0f, 20.0f);
_pastseck = 0.0f;
}
if (_pastseck < 0.5f)
{
_Kuchi_Weight += (Time.deltaTime / 0.4f) * 100f;
if (_Kuchi_Weight > 99.9f) _Kuchi_Weight = 100f;
m_Face.SetBlendShapeWeight(s2i(_kuchiake_shapekey), _Kuchi_Weight);
}
else if (_pastseck > 2.0f && _pastseck <= 2.5f)
{
_Kuchi_Weight -= (Time.deltaTime / 0.4f) * 100f;
if (_Kuchi_Weight < 0.01f) _Kuchi_Weight = 0f;
m_Face.SetBlendShapeWeight(s2i(_kuchiake_shapekey), _Kuchi_Weight);
}
}
public void Move2(Vector3 move, int nyaa)
{
if (move.magnitude > 1f) move.Normalize();
move = transform.InverseTransformDirection(move);
CheckGroundStatus();
move = Vector3.ProjectOnPlane(move, m_GroundNormal);
_TurnAmount = Mathf.Atan2(move.x, move.z);
_ForwardAmount = move.z;
ApplyExtraTurnRotation();
_Nyaa = nyaa;
UpdateAnimator(move);
}
void UpdateAnimator(Vector3 move)
{
m_Animator.SetFloat("Forward", _ForwardAmount, 0.1f, Time.deltaTime);
m_Animator.SetFloat("Turn", _TurnAmount, 0.1f, Time.deltaTime);
m_Animator.SetInteger("Nyaa", _Nyaa);
if (_Nyaa > 0)
{
pastnyaatime += Time.deltaTime;
if (pastnyaatime > nextnyaatime)
{
pastnyaatime = 0f;
nextnyaatime = Random.Range(0.5f, 2.0f);
m_Animator.Play(m_Animator.GetCurrentAnimatorStateInfo(1).shortNameHash, 1, 0f);
}
}
m_Animator.speed = (move.magnitude > 0) ? _AnimSpeedMultiplier : 1f;
if (_Nyaa > 0)
{
_nyaa_point++;
if (_nyaa_point < 1000)
{
foreach (string name in _nyaa2_shapekeys) m_Face.SetBlendShapeWeight(s2i(name), 0f);
foreach (string name in _nyaa1_shapekeys) m_Face.SetBlendShapeWeight(s2i(name), 100f);
foreach (string name in _nyaa1_shapekeys_rev) m_Face.SetBlendShapeWeight(s2i(name), 0f);
_mabataki_on = true;
}
else if (_nyaa_point < 1600)
{
foreach (string name in _nyaa1_shapekeys) m_Face.SetBlendShapeWeight(s2i(name), 0f);
foreach (string name in _nyaa2_shapekeys) m_Face.SetBlendShapeWeight(s2i(name), 100f);
foreach (string name in _nyaa2_shapekeys_rev) m_Face.SetBlendShapeWeight(s2i(name), 0f);
_mabataki_on = false;
}
else if (_nyaa_point >= 1600)
{
_nyaa_point = 0;
}
}
else if (_Nyaa == 0)
{
foreach (string name in _nyaa1_shapekeys) m_Face.SetBlendShapeWeight(s2i(name), 0f);
foreach (string name in _nyaa2_shapekeys) m_Face.SetBlendShapeWeight(s2i(name), 0f);
_mabataki_on = true;
_nyaa_point--;
if (_nyaa_point < 0) _nyaa_point = 0;
}
}
void ApplyExtraTurnRotation()
{
float turnSpeed = Mathf.Lerp(_StationaryTurnSpeed, _MovingTurnSpeed, _ForwardAmount);
transform.Rotate(0, _TurnAmount * turnSpeed * Time.deltaTime, 0);
}
public void OnAnimatorMove()
{
if (Time.deltaTime > 0)
{
Vector3 v = (m_Animator.deltaPosition * _MoveSpeedMultiplier) / Time.deltaTime;
v.y = m_Rigidbody.velocity.y;
m_Rigidbody.velocity = v;
}
}
void CheckGroundStatus()
{
RaycastHit hitInfo;
#if UNITY_EDITOR
Debug.DrawLine(transform.position + (Vector3.up * 0.1f), transform.position + (Vector3.up * 0.1f) + (Vector3.down * _GroundCheckDistance));
#endif
if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hitInfo, _GroundCheckDistance))
{
m_GroundNormal = hitInfo.normal;
}
else
{
m_GroundNormal = Vector3.up;
}
}
}