using System.Collections;
using System.Collections.Generic;
using Platformer.Core;
using Platformer.Model;
using UnityEngine;
namespace Platformer.Mechanics
{
///
/// AnimationController integrates physics and animation. It is generally used for simple enemy animation.
///
// BT12-Dev 2026-05-12 — Visual 자식 분리: RequireComponent SpriteRenderer·Animator 폐기.
// GetComponentInChildren fallback로 Visual 자식 영역 영역 영역.
public class AnimationController : KinematicObject
{
///
/// Max horizontal speed.
///
public float maxSpeed = 7;
///
/// Max jump velocity
///
public float jumpTakeOffSpeed = 7;
///
/// Used to indicated desired direction of travel.
///
public Vector2 move;
///
/// Set to true to initiate a jump.
///
public bool jump;
///
/// Set to true to set the current jump velocity to zero.
///
public bool stopJump;
SpriteRenderer spriteRenderer;
Animator animator;
PlatformerModel model;
protected virtual void Awake()
{
// BT12-Dev 2026-05-12 — Visual 자식 분리 (PD 지시): SpriteRenderer·Animator가 자식 Visual GameObject에 위치할 수 있음.
spriteRenderer = GetComponent();
if (spriteRenderer == null) spriteRenderer = GetComponentInChildren();
animator = GetComponent();
if (animator == null) animator = GetComponentInChildren();
// BT12-Dev 2026-05-12 — field initializer Awake 영역 이동 (Editor·Play mode 전환 시 model 미초기화 NRE 회피).
try { model = Simulation.GetModel(); } catch { model = null; }
// BT12-Dev 2026-05-12 — KinematicObject base 영역 protected virtual OnEnable/Start/Update/FixedUpdate Unity 호출 X 정정
// (override X·derived class만 magic method 영역). Awake 영역 base 초기화 위임.
body = GetComponent();
if (body != null) body.bodyType = RigidbodyType2D.Kinematic;
contactFilter.useTriggers = false;
contactFilter.SetLayerMask(Physics2D.GetLayerCollisionMask(gameObject.layer));
contactFilter.useLayerMask = true;
}
// BT12-Dev 2026-05-12 — Update·FixedUpdate Unity 호출 정합 (override 영역 derived 영역 호출 영역)
protected override void Update()
{
base.Update();
}
protected override void FixedUpdate()
{
base.FixedUpdate();
}
protected override void ComputeVelocity()
{
float jumpMod = model != null ? model.jumpModifier : 1f;
float jumpDec = model != null ? model.jumpDeceleration : 0.5f;
if (jump && IsGrounded)
{
velocity.y = jumpTakeOffSpeed * jumpMod;
jump = false;
}
else if (stopJump)
{
stopJump = false;
if (velocity.y > 0)
{
velocity.y = velocity.y * jumpDec;
}
}
// PD 명시 2026-05-08 — PlayerController와 동일 영역 정합: 좌측 향한 sprite 기준 우측 이동 시 flipX=true
if (spriteRenderer != null)
{
if (move.x > 0.01f) spriteRenderer.flipX = true;
else if (move.x < -0.01f) spriteRenderer.flipX = false;
}
if (animator != null)
{
animator.SetBool("grounded", IsGrounded);
animator.SetFloat("velocityX", Mathf.Abs(velocity.x) / maxSpeed);
}
targetVelocity = move * maxSpeed;
}
}
}