
오늘 학습 키워드
최종 팀 프로젝트
오늘 학습 한 내용을 나만의 언어로 정리하기
플레이어 포션 먹기
- 플레이어가 포션 먹을 때 다른 행동 못하게 해서 오히려 쉬웠음
public class PotionState : IPlayerState
{
private float startStateTime;
private float startPotionTime = 0.01f;
private float animRunningTime = 0f;
private float potionAnimationLength;
public void Enter(PlayerController controller)
{
animRunningTime = 0f;
startStateTime = Time.time;
potionAnimationLength =
controller.Animator.animator.runtimeAnimatorController
.animationClips.First(c => c.name == "Potion").length;
controller.Animator.ClearBool();
controller.Animator.SetTriggerAnimation(PlayerAnimID.Potion);
Debug.Log("[플레이어] 체력 회복 시도");
}
public void HandleInput(PlayerController controller)
{
}
public void LogicUpdate(PlayerController controller)
{
animRunningTime += Time.deltaTime;
if (Time.time - startStateTime > startPotionTime)
{
AnimatorStateInfo curAnimInfo = controller.Animator.animator.GetCurrentAnimatorStateInfo(0);
if (curAnimInfo.IsName("Potion"))
{
float animTime = curAnimInfo.normalizedTime;
if (animTime >= 1.0f)
{
controller.Condition.potionCount--;
controller.Condition.health.Add(controller.Condition.potionHealthRecovery);
Debug.Log($"[플레이어] 체력 회복됨 {controller.Condition.health.CurValue()}");
controller.ChangeState<IdleState>();
return;
}
}
if (animRunningTime >= potionAnimationLength)
{
controller.Condition.potionCount--;
controller.Condition.health.Add(controller.Condition.potionHealthRecovery);
Debug.Log($"[플레이어] 체력 회복됨 {controller.Condition.health.CurValue()}");
controller.ChangeState<IdleState>();
return;
}
}
}
public void Exit(PlayerController controller)
{
}
}- 애니메이션 송출이 다 끝나야지 체력이 회복되도록 했음
추가 스킬 만들기
- 리플렉션을 쓰기로 함
- 우선 모든 스킬은 SkillBase를 상속하게 함
- 그리고 Skill Name과 동일한 이름의 스킬 클래스를 만듬
- 게임이 시작할 때 PlayerSkillManager에 모든 스킬들을 다 박아둠
- 그리고 로그인하면 플레이어가 어떤 스킬을 가지고 있는지가 나옴.
- 거기서 어떤 스킬을 사용할지 선택할 수 있음.
그래서 리플렉션 어떻게 쓰는데요
- Assembly.GetExecutingAssembly().GetType() : 어셈블리에서 이름이 같은 클래스 타입을 찾아서 타입 정보 를 돌려줌. ⇒ 인스턴스 없음.
- Assembly.GetExecutingAssembly().CreateInstance() : 인스턴스까지 만들어줌. 대신 기본 생성자를 씀
- 커스텀 생성자 쓰고싶으면 Activator.CreateInstance(type, args) 를 써야함
- 이번 경우에는 기본 생성자를 쓰는 대신에 그 클래스의 Init 함수를 불러주는 형식으로 했음.
private void LoadSkills()
{
List<PlayerSkillModel> skillModels = DataManager.Instance.PlayerSkillDataList.DataList;
foreach (var skillModel in skillModels)
{
skills[skillModel.skillId] = CreateSkill(skillModel.skillId, skillModel.skillName);
}
Debug.Log($"[플레이어] 스킬 세트 준비 완료");
}
private SkillBase CreateSkill(int skillId, string skillName)
{
if (!skills.TryGetValue(skillId, out SkillBase skill))
{
Type skillType = Assembly.GetExecutingAssembly().GetType(skillName);
if (skillType == null)
{
Debug.LogError($"[플레이어] 스킬 클래스 {skillName} 을 찾을 수 없삼");
return null;
}
if (!DataManager.Instance.PlayerSkillDataList.TryGetPlayerSkillModelData(skillId, out var skillModel))
{
Debug.LogError($"[플레이어] 스킬 아이디 {skillId} 는 없는 아이디임");
return null;
}
SkillBase newSkill = Activator.CreateInstance(skillType) as SkillBase;
if (newSkill == null) return null;
newSkill.Init(
skillModel.skillId, skillModel.damage, skillModel.damage2, skillModel.buffValue,
skillModel.stamina, skillModel.cooldown, skillModel.duration
);
Debug.Log($"[플레이어] 스킬 클래스 {skillName} 을 생성함");
return newSkill;
}
else return skill;
}포션 먹는걸 티내봐요
- 포션을 먹을 때 바로 Observable을 써서 이벤트버스 발동하게 함
// PlayerCondition.cs
[Header("Potion Settings")]
[HideInInspector] public Observable<bool> getPotion;
public int potionCount = 1;
public int potionHealthRecovery = 3;
private PlayerController controller;
private Coroutine invincibleCoroutine;
[HideInInspector] public Observable<bool> isDead;
private void Awake()
{
canStaminaRecovery = new Observable<bool>(EventBusKey.ChangeStaminaRecovery, false);
isDead = new Observable<bool>(EventBusKey.ChangePlayerDead, false);
getPotion = new Observable<bool>(EventBusKey.GetPotion, false);
controller = GetComponent<PlayerController>();
}