Compare commits
19 Commits
f8e7f539d7
...
28c72be3b8
Author | SHA1 | Date | |
---|---|---|---|
|
28c72be3b8 | ||
5dcde907a1 | |||
|
2708df17df | ||
|
882ef3b8dc | ||
|
d0d42cf551 | ||
|
ea45936114 | ||
|
18211fff05 | ||
|
50e5b8db98 | ||
|
393b538920 | ||
|
bc88d47e6b | ||
b5a39714f0 | |||
|
e1c1f6a329 | ||
|
99082eeb7c | ||
|
406dc8f84f | ||
|
c262b9e2f7 | ||
|
cdded898ec | ||
|
2ebeccfa69 | ||
4e7ca0526c | |||
|
976cfc793a |
13
.idea/.idea.Degulleo3D116Rework/.idea/.gitignore
generated
vendored
Normal file
13
.idea/.idea.Degulleo3D116Rework/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# 디폴트 무시된 파일
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider에서 무시된 파일
|
||||
/contentModel.xml
|
||||
/projectSettingsUpdater.xml
|
||||
/modules.xml
|
||||
/.idea.Degulleo3D116Rework.iml
|
||||
# 에디터 기반 HTTP 클라이언트 요청
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
8
.idea/.idea.Degulleo3D116Rework/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.Degulleo3D116Rework/.idea/indexLayout.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
6
.idea/.idea.Degulleo3D116Rework/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.Degulleo3D116Rework/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
8
Assets/JYY/Prefabs/Bullets.meta
Normal file
8
Assets/JYY/Prefabs/Bullets.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37e30a87d9c904c898232118c82b5fbc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
Assets/JYY/Prefabs/Bullets/Dummy Magic Missaile.prefab
(Stored with Git LFS)
Normal file
BIN
Assets/JYY/Prefabs/Bullets/Dummy Magic Missaile.prefab
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b14d6aa88de82f449e47d835ebf73c7
|
||||
guid: 9c16b44c8736e4007ad5f0733ce433e1
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
BIN
Assets/JYY/Prefabs/[Enemy] Dummy Monster.prefab
(Stored with Git LFS)
Normal file
BIN
Assets/JYY/Prefabs/[Enemy] Dummy Monster.prefab
(Stored with Git LFS)
Normal file
Binary file not shown.
7
Assets/JYY/Prefabs/[Enemy] Dummy Monster.prefab.meta
Normal file
7
Assets/JYY/Prefabs/[Enemy] Dummy Monster.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06eebdb9d2c03437fb632d9e15fd1078
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
Assets/JYY/Scenes/MonsterTest.unity
(Stored with Git LFS)
BIN
Assets/JYY/Scenes/MonsterTest.unity
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/LIN/Housing Copy.unity
(Stored with Git LFS)
BIN
Assets/LIN/Housing Copy.unity
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/LIN/Prefabs/Canvas.prefab
(Stored with Git LFS)
BIN
Assets/LIN/Prefabs/Canvas.prefab
(Stored with Git LFS)
Binary file not shown.
BIN
Assets/LIN/Prefabs/HousingMainUIPanel_Copy.prefab
(Stored with Git LFS)
BIN
Assets/LIN/Prefabs/HousingMainUIPanel_Copy.prefab
(Stored with Git LFS)
Binary file not shown.
8
Assets/LIN/Scripts.meta
Normal file
8
Assets/LIN/Scripts.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94531ff12d388974a9a50a9e33997d6e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -12,6 +12,7 @@ public class InteractionController : MonoBehaviour
|
||||
[FormerlySerializedAs("housingCanvasManager")]
|
||||
[Header("UI 연동")]
|
||||
[SerializeField] HousingCanvasController housingCanvasController;
|
||||
[SerializeField] private InteractionAnimationPanelController interactionAnimationPanelController;
|
||||
|
||||
private SuddenEventController _suddenEventController = new SuddenEventController();
|
||||
|
||||
@ -38,6 +39,7 @@ public class InteractionController : MonoBehaviour
|
||||
if (interactionLayerMask == (interactionLayerMask | (1 << other.gameObject.layer)))
|
||||
{
|
||||
housingCanvasController.HideInteractionButton();
|
||||
housingCanvasController.interactionTextsController.InitInteractionTexts();
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,11 +53,12 @@ public class InteractionController : MonoBehaviour
|
||||
if (playerStats.CanPerformByHealth(interactionType))
|
||||
{
|
||||
playerStats.PerformAction(interactionType);
|
||||
interactionAnimationPanelController.ShowAnimationPanel(interactionType,interactionTexts.AnimationText);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
housingCanvasController.SetActionText(interactionTexts.LackOfHealth);
|
||||
housingCanvasController.SetDescriptionText();
|
||||
housingCanvasController.interactionTextsController.ActiveTexts(interactionTexts.LackOfHealth);
|
||||
}
|
||||
});
|
||||
}
|
8
Assets/LIN/Scripts/UI.meta
Normal file
8
Assets/LIN/Scripts/UI.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5a9f238e478db241bcae4cd9192a195
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -3,14 +3,14 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class HousingCanvasController : MonoBehaviour
|
||||
{
|
||||
[Header("일상행동 상호작용")]
|
||||
[SerializeField] GameObject interactionButton;
|
||||
[SerializeField] TMP_Text actionText;
|
||||
[SerializeField] TMP_Text descriptionText;
|
||||
|
||||
[SerializeField] private GameObject interactionButton;
|
||||
public InteractionTextsContoller interactionTextsController;
|
||||
|
||||
[Header("돌발 이벤트")]
|
||||
[SerializeField] private GameObject suddenPanel;
|
||||
[SerializeField] private TMP_Text suddenText;
|
||||
@ -20,34 +20,16 @@ public class HousingCanvasController : MonoBehaviour
|
||||
|
||||
void Awake()
|
||||
{
|
||||
InitInteractionTexts();
|
||||
interactionTextsController.InitInteractionTexts();
|
||||
interactionButton.SetActive(false);
|
||||
suddenPanel.SetActive(false);
|
||||
}
|
||||
|
||||
#region 상호작용 일상 행동
|
||||
//사물 이름 세팅
|
||||
public void SetActionText(string text = "")
|
||||
{
|
||||
actionText.text = text;
|
||||
}
|
||||
//사물 상호작용 내용 설명
|
||||
public void SetDescriptionText(string text = "")
|
||||
{
|
||||
descriptionText.text = text;
|
||||
}
|
||||
|
||||
private void InitInteractionTexts()
|
||||
{
|
||||
SetActionText();
|
||||
SetDescriptionText();
|
||||
}
|
||||
|
||||
// 상호작용 가능한 사물에 가까이 갔을 때 화면에 텍스트, 버튼 표시
|
||||
public void ShowInteractionButton(string actText, string descText,Action onInteractionButtonPressed)
|
||||
{
|
||||
SetActionText(actText);
|
||||
SetDescriptionText(descText);
|
||||
interactionTextsController.ActiveTexts(actText, descText);
|
||||
interactionButton.SetActive(true);
|
||||
|
||||
//각 행동 별로 실행되어야 할 이벤트 구독
|
||||
@ -56,8 +38,6 @@ public class HousingCanvasController : MonoBehaviour
|
||||
//범위에서 벗어나면 상호작용 버튼 off
|
||||
public void HideInteractionButton()
|
||||
{
|
||||
SetActionText();
|
||||
SetDescriptionText();
|
||||
interactionButton.SetActive(false);
|
||||
|
||||
//구독해놓은 이벤트 해제
|
||||
@ -67,8 +47,13 @@ public class HousingCanvasController : MonoBehaviour
|
||||
//상호작용 버튼 눌렀을 때
|
||||
public void OnClickInteractionButton()
|
||||
{
|
||||
//상호작용 별 행동 수행
|
||||
OnInteractionButtonPressed?.Invoke();
|
||||
OnInteractionButtonPressed = null;
|
||||
|
||||
//상호작용 버튼과 텍스트 숨김
|
||||
HideInteractionButton();
|
||||
interactionTextsController.InitInteractionTexts();
|
||||
}
|
||||
#endregion
|
||||
|
@ -20,10 +20,15 @@ public static class HousingConstants
|
||||
public static readonly Dictionary<ActionType, InteractionTexts> interactions =
|
||||
new Dictionary<ActionType, InteractionTexts>
|
||||
{
|
||||
{ ActionType.Sleep, new InteractionTexts("침대에서 잘까?","숙면으로 시간 당 체력 1을 회복한다.", ".")},
|
||||
{ ActionType.Housework, new InteractionTexts("밀린 집안일을 처리할까?","체력 1을 사용하고 좋은일이 일어날지도 모른다","힘들어서 못해..")},
|
||||
{ ActionType.Dungeon, new InteractionTexts("던전에 입장할까?","체력 3을 사용하고 3시간이 흐른다.","던전에 갈 체력이 되지 않아..")},
|
||||
{ ActionType.Work, new InteractionTexts("출근한다.","체력 3을 사용하고 저녁 6시에나 돌아오겠지..", "도저히 출근할 체력이 안되는걸..?")}
|
||||
{ ActionType.Sleep, new InteractionTexts("침대에서 잘까?","숙면으로 시간 당 체력 1을 회복한다.",
|
||||
".","쿨쿨 자는 중")},
|
||||
{ ActionType.Housework, new InteractionTexts("밀린 집안일을 처리할까?","체력 1을 사용하고 좋은일이 일어날지도 모른다",
|
||||
"힘들어서 못해..","세탁하는 중")},
|
||||
{ ActionType.Dungeon, new InteractionTexts("던전에 입장할까?","체력 3을 사용하고 3시간이 흐른다.",
|
||||
"던전에 갈 체력이 되지 않아..","던전 진입하는 중")},
|
||||
{ ActionType.Work, new InteractionTexts("출근한다.","체력 3을 사용하고 저녁 6시에나 돌아오겠지..",
|
||||
"도저히 출근할 체력이 안되는걸..?","출근하는 중")},
|
||||
{ActionType.Eat, new InteractionTexts("식사를 하자","1시간 동안 체력 1을 회복한다.","밥 먹는 중")}
|
||||
};
|
||||
#endregion
|
||||
|
||||
@ -32,12 +37,14 @@ public static class HousingConstants
|
||||
public string ActionText { get; private set; }
|
||||
public string DescriptionText { get; private set; }
|
||||
public string LackOfHealth { get; private set; }
|
||||
public string AnimationText { get; private set; }
|
||||
|
||||
public InteractionTexts(string actionText, string descriptionText, string lackOfHealth)
|
||||
public InteractionTexts(string actionText, string descriptionText, string lackOfHealth, string animationText = "")
|
||||
{
|
||||
ActionText = actionText;
|
||||
DescriptionText = descriptionText;
|
||||
LackOfHealth = lackOfHealth;
|
||||
AnimationText = animationText;
|
||||
}
|
||||
}
|
||||
}
|
106
Assets/LIN/Scripts/UI/InteractionAnimationPanelController.cs
Normal file
106
Assets/LIN/Scripts/UI/InteractionAnimationPanelController.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class InteractionAnimationPanelController : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject panel;
|
||||
[SerializeField] private Image doingImage;
|
||||
[SerializeField] private TMP_Text doingText;
|
||||
[SerializeField] private Animator animator;
|
||||
[SerializeField] private float animationDuration = 2.0f;
|
||||
|
||||
private Coroutine _textAnimCoroutine;
|
||||
private Coroutine _autoHideCoroutine;
|
||||
|
||||
public void SetDoingText(string text)
|
||||
{
|
||||
doingText.text = text;
|
||||
}
|
||||
|
||||
public void ShowAnimationPanel(ActionType actionType, string animationText)
|
||||
{
|
||||
// 1) 패널 활성화
|
||||
panel.SetActive(true);
|
||||
// 2) 기존 코루틴 정리
|
||||
if (_textAnimCoroutine != null) StopCoroutine(_textAnimCoroutine);
|
||||
if (_autoHideCoroutine != null) StopCoroutine(_autoHideCoroutine);
|
||||
|
||||
// 3) 텍스트 및 애니메이션 세팅
|
||||
doingText.text = animationText;
|
||||
switch (actionType)
|
||||
{
|
||||
case ActionType.Sleep:
|
||||
break;
|
||||
case ActionType.Work:
|
||||
break;
|
||||
case ActionType.Eat:
|
||||
break;
|
||||
case ActionType.Dungeon:
|
||||
break;
|
||||
case ActionType.Housework:
|
||||
animator.Play("Laundry");
|
||||
break;
|
||||
}
|
||||
_textAnimCoroutine = StartCoroutine(TextDotsAnimation());
|
||||
_autoHideCoroutine = StartCoroutine(AutoHidePanel());
|
||||
}
|
||||
|
||||
private IEnumerator TextDotsAnimation()
|
||||
{
|
||||
var tempText = doingText.text;
|
||||
float startTime = Time.time;
|
||||
while (Time.time - startTime < 3)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
yield return new WaitForSeconds(0.3f);
|
||||
doingText.text = tempText + new string('.', i + 1);
|
||||
}
|
||||
yield return new WaitForSeconds(0.3f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 패널이 2초후 자동으로 닫히거나 터치시 닫히도록 합니다.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerator AutoHidePanel()
|
||||
{
|
||||
float startTime = Time.time;
|
||||
while (Time.time - startTime < animationDuration)
|
||||
{
|
||||
if (Input.touchCount > 0 || Input.GetMouseButtonDown(0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
|
||||
//패널 닫고 애니메이션 null처리
|
||||
HidePanel();
|
||||
_autoHideCoroutine = null;
|
||||
}
|
||||
|
||||
private void HidePanel()
|
||||
{
|
||||
panel.SetActive(false);
|
||||
|
||||
if (_textAnimCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_textAnimCoroutine);
|
||||
_textAnimCoroutine = null;
|
||||
}
|
||||
|
||||
if (_autoHideCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_autoHideCoroutine);
|
||||
_autoHideCoroutine = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a67d1bf02c4a3d34cb1b9709d9930fa1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
41
Assets/LIN/Scripts/UI/InteractionTextsContoller.cs
Normal file
41
Assets/LIN/Scripts/UI/InteractionTextsContoller.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class InteractionTextsContoller : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject textsPanel;
|
||||
[SerializeField] TMP_Text actionText;
|
||||
[SerializeField] TMP_Text _descriptionText;
|
||||
|
||||
public void SetActionText(string text)
|
||||
{
|
||||
actionText.text = text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Panel 활성화를 끄고 텍스트들을 초기화 합니다.
|
||||
/// </summary>
|
||||
public void InitInteractionTexts()
|
||||
{
|
||||
textsPanel.SetActive(false);
|
||||
SetActionText("");
|
||||
_descriptionText.text = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 특정 범위 안에 상호작용 물체가 들어왔을 때, 상호작용 텍스트 패널을 활성화시킴
|
||||
/// </summary>
|
||||
/// <param name="actionText">상호작용할 내용</param>
|
||||
/// <param name="_descriptionText">스테이터스 변경에 대한 설명</param>
|
||||
public void ActiveTexts(string actionText, string descriptionText = "")
|
||||
{
|
||||
SetActionText(actionText);
|
||||
_descriptionText.text = descriptionText;
|
||||
textsPanel.SetActive(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
11
Assets/LIN/Scripts/UI/InteractionTextsContoller.cs.meta
Normal file
11
Assets/LIN/Scripts/UI/InteractionTextsContoller.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a9631c7b5512cc4ab41bbca8c17b945
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
277317
Assets/LYM/Fonts/Galmuri9 SDF new.asset
Normal file
277317
Assets/LYM/Fonts/Galmuri9 SDF new.asset
Normal file
File diff suppressed because one or more lines are too long
8
Assets/LYM/Fonts/Galmuri9 SDF new.asset.meta
Normal file
8
Assets/LYM/Fonts/Galmuri9 SDF new.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80e8f592861964445a697bb8c8fee37d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because one or more lines are too long
BIN
Assets/LYM/Scenes/MainUI.unity
(Stored with Git LFS)
Normal file
BIN
Assets/LYM/Scenes/MainUI.unity
(Stored with Git LFS)
Normal file
Binary file not shown.
7
Assets/LYM/Scenes/MainUI.unity.meta
Normal file
7
Assets/LYM/Scenes/MainUI.unity.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe5619f467b6e0f42b57ee216ffdd7c7
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Scripts/Character/Enemy/Bullet.meta
Normal file
8
Assets/Scripts/Character/Enemy/Bullet.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a636af603b3af4d1baccb8296add7485
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
75
Assets/Scripts/Character/Enemy/Bullet/BulletBase.cs
Normal file
75
Assets/Scripts/Character/Enemy/Bullet/BulletBase.cs
Normal file
@ -0,0 +1,75 @@
|
||||
using UnityEngine;
|
||||
|
||||
public struct BulletData
|
||||
{
|
||||
public Vector3 TargetPos;
|
||||
public float Damage;
|
||||
public float LifeTime;
|
||||
public float Speed;
|
||||
|
||||
public BulletData(Vector3 targetPos, float damage, float lifeTime, float speed)
|
||||
{
|
||||
TargetPos = targetPos;
|
||||
Damage = damage;
|
||||
LifeTime = lifeTime;
|
||||
Speed = speed;
|
||||
}
|
||||
}
|
||||
[RequireComponent(typeof(Collider))]
|
||||
public class BulletBase : MonoBehaviour
|
||||
{
|
||||
// 데이터
|
||||
private float _speed = 5f;
|
||||
private float _damage = 1f;
|
||||
private float _lifeTime = 10f;
|
||||
|
||||
// 내부용
|
||||
private Vector3 _direction = Vector3.forward;
|
||||
private float _timer;
|
||||
|
||||
public virtual void Initialize(BulletData bulletData)
|
||||
{
|
||||
_speed = bulletData.Speed;
|
||||
_damage = bulletData.Damage;
|
||||
_lifeTime = bulletData.LifeTime;
|
||||
|
||||
// 발사 위치 기준 목표 방향만 계산
|
||||
_direction = (bulletData.TargetPos - transform.position).normalized;
|
||||
|
||||
// 탄환이 바라보는 방향 세팅
|
||||
transform.rotation = Quaternion.LookRotation(_direction);
|
||||
|
||||
_timer = 0f;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 1) 이동
|
||||
transform.position += _direction * (_speed * Time.deltaTime);
|
||||
|
||||
// 2) 수명 카운트
|
||||
_timer += Time.deltaTime;
|
||||
if (_timer >= _lifeTime)
|
||||
{
|
||||
DestroyBullet();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
// TODO: 주인공 캐릭터를 찾는 로직 추가 필요
|
||||
// 주인공 스크립트를 찾아 처리할 것.
|
||||
var character = other.GetComponent<CharacterBase>();
|
||||
if (character != null)
|
||||
{
|
||||
character.TakeDamage(_damage);
|
||||
DestroyBullet();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DestroyBullet()
|
||||
{
|
||||
Debug.Log("## Bullet destroyed");
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
3
Assets/Scripts/Character/Enemy/Bullet/BulletBase.cs.meta
Normal file
3
Assets/Scripts/Character/Enemy/Bullet/BulletBase.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c349f971ec844b19d94a06e8f93aca0
|
||||
timeCreated: 1745890918
|
8
Assets/Scripts/Character/Enemy/Bullet/MagicMissile.cs
Normal file
8
Assets/Scripts/Character/Enemy/Bullet/MagicMissile.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MagicMissile : BulletBase
|
||||
{
|
||||
|
||||
}
|
11
Assets/Scripts/Character/Enemy/Bullet/MagicMissile.cs.meta
Normal file
11
Assets/Scripts/Character/Enemy/Bullet/MagicMissile.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc3f5b56a395f448c881888076d83cba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -4,16 +4,121 @@ using UnityEngine;
|
||||
|
||||
public class CasterDemonController : EnemyController
|
||||
{
|
||||
private bool _doneBattleSequence = true;
|
||||
private bool _isFirstNoPath = true;
|
||||
|
||||
[SerializeField] private Transform teleportTransform;
|
||||
[SerializeField] private Transform bulletShotPosition;
|
||||
[SerializeField] private GameObject magicMissilePrefab;
|
||||
[SerializeField] private GameObject teleportEffectPrefab;
|
||||
public override void BattleSequence()
|
||||
{
|
||||
// TODO : 배틀 중일 때 루프
|
||||
Debug.Log("## 몬스터의 교전 행동 루프");
|
||||
// 전투 행동이 이미 진행 중일 경우 실행 막기
|
||||
if (_doneBattleSequence)
|
||||
{
|
||||
// 전투 행동 시작
|
||||
_doneBattleSequence = false;
|
||||
|
||||
// TODO : 배틀 중일 때 루프
|
||||
Debug.Log("## 몬스터의 교전 행동 루프");
|
||||
Thinking();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Thinking()
|
||||
{
|
||||
int selectedPattern = Random.Range(0, 10);
|
||||
|
||||
switch (selectedPattern)
|
||||
{
|
||||
case 0:
|
||||
|
||||
case 1:
|
||||
|
||||
case 2:
|
||||
|
||||
case 3:
|
||||
|
||||
case 4:
|
||||
|
||||
case 5:
|
||||
|
||||
case 6:
|
||||
|
||||
case 7:
|
||||
|
||||
case 8:
|
||||
|
||||
case 9:
|
||||
StartCoroutine(ShotMagicMissile());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnCannotFleeBehaviour()
|
||||
{
|
||||
Debug.Log("## 몬스터가 막다른 길에 몰려 뭔가 함");
|
||||
// 구석에 끼인 경우 탈출
|
||||
|
||||
Debug.Log("## 텔레포트 시전");
|
||||
Teleport();
|
||||
}
|
||||
|
||||
private IEnumerator ShotMagicMissile()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
// 1. 기본 위치
|
||||
Vector3 basePos = TraceTargetTransform.position;
|
||||
Vector3 aimPosition = basePos;
|
||||
|
||||
// 2. 플레이어 Rigidbody로 속도 얻기
|
||||
if (TraceTargetTransform.TryGetComponent<Rigidbody>(out var rb))
|
||||
{
|
||||
// 아주 짧은 시간만 예측
|
||||
float predictionTime = 0.3f;
|
||||
aimPosition += rb.velocity * predictionTime;
|
||||
}
|
||||
|
||||
// 높이는 변경할 필요 없음
|
||||
float fixedY = bulletShotPosition.position.y;
|
||||
aimPosition.y = fixedY;
|
||||
|
||||
// 3. 그 위치를 바라보고
|
||||
transform.LookAt(aimPosition);
|
||||
|
||||
// 4. 미사일 생성 및 초기화
|
||||
var missile = Instantiate(
|
||||
magicMissilePrefab,
|
||||
bulletShotPosition.position,
|
||||
transform.rotation
|
||||
);
|
||||
missile.GetComponent<MagicMissile>()
|
||||
.Initialize(new BulletData(aimPosition, 5f, 10f, 5f));
|
||||
|
||||
yield return new WaitForSeconds(0.4f);
|
||||
}
|
||||
|
||||
// 짧은 텀 후 끝내기
|
||||
yield return new WaitForSeconds(1f);
|
||||
_doneBattleSequence = true;
|
||||
}
|
||||
|
||||
private void Teleport()
|
||||
{
|
||||
if (teleportEffectPrefab != null)
|
||||
Instantiate(teleportEffectPrefab, transform.position, Quaternion.identity);
|
||||
|
||||
if (Agent != null && teleportTransform != null)
|
||||
Agent.Warp(teleportTransform.position);
|
||||
else if (teleportTransform != null)
|
||||
transform.position = teleportTransform.position;
|
||||
|
||||
if (teleportEffectPrefab != null && teleportTransform != null)
|
||||
Instantiate(teleportEffectPrefab, teleportTransform.position, Quaternion.identity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,11 @@ public class EnemyStateFlee :IEnemyState
|
||||
private EnemyController _enemyController;
|
||||
private Transform _playerTransform;
|
||||
private float _fleeDistance = 5f; // 도망치는 거리
|
||||
private float _attackRange = 7f; // 공격 범위
|
||||
private float _safeRange = 7f; // 공격 범위
|
||||
|
||||
// 경로 탐색 주기 조절용
|
||||
private float _fleeSearchTimer = 0;
|
||||
private float _fleeThresholdTime = 0.2f;
|
||||
|
||||
// 막다른길 검사용
|
||||
private Vector3 _lastPosition;
|
||||
@ -21,9 +25,11 @@ public class EnemyStateFlee :IEnemyState
|
||||
|
||||
_playerTransform = _enemyController.TraceTargetTransform;
|
||||
_lastPosition = _enemyController.transform.position;
|
||||
|
||||
_enemyController.Agent.ResetPath();
|
||||
_enemyController.Agent.isStopped = false;
|
||||
_stuckTimer = 0f;
|
||||
|
||||
|
||||
_fleeSearchTimer = 0;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@ -34,8 +40,28 @@ public class EnemyStateFlee :IEnemyState
|
||||
return;
|
||||
}
|
||||
|
||||
float currentDist = Vector3.Distance(
|
||||
_enemyController.transform.position,
|
||||
_playerTransform.position
|
||||
);
|
||||
if (currentDist >= _safeRange)
|
||||
{
|
||||
// 목적지 리셋 후 전투 시작
|
||||
_enemyController.Agent.isStopped = true;
|
||||
_enemyController.Agent.ResetPath();
|
||||
_enemyController.BattleSequence();
|
||||
return;
|
||||
}
|
||||
|
||||
FindPositionFlee();
|
||||
|
||||
if (!_enemyController.Agent.pathPending &&
|
||||
_enemyController.Agent.pathStatus == NavMeshPathStatus.PathInvalid)
|
||||
{
|
||||
Debug.Log("## 길을 못찾음");
|
||||
HandleDeadEnd();
|
||||
}
|
||||
|
||||
// 막힘 감지 (실제 이동 체크)
|
||||
CheckPath();
|
||||
|
||||
@ -44,45 +70,39 @@ public class EnemyStateFlee :IEnemyState
|
||||
|
||||
private void CheckPath()
|
||||
{
|
||||
float distance = Vector3.Distance(_enemyController.transform.position, _playerTransform.position);
|
||||
if (distance < StuckMoveThreshold)
|
||||
float moved = Vector3.Distance(_enemyController.transform.position, _lastPosition);
|
||||
if (moved < StuckMoveThreshold)
|
||||
{
|
||||
_stuckTimer += Time.deltaTime;
|
||||
if (_stuckTimer >= StuckThresholdTime)
|
||||
{
|
||||
// 막다른 길임 : 대체 행동 실행
|
||||
|
||||
Debug.Log("## 끼임");
|
||||
HandleDeadEnd();
|
||||
_stuckTimer = 0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 정상적인 길: 배틀 루프 실행
|
||||
_enemyController.BattleSequence();
|
||||
_stuckTimer = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void FindPositionFlee()
|
||||
{
|
||||
_fleeSearchTimer += Time.deltaTime;
|
||||
if (_fleeSearchTimer <= _fleeThresholdTime) return;
|
||||
|
||||
// 1) 목표 도망 위치 계산
|
||||
Vector3 fleeDirection = (_enemyController.transform.position - _playerTransform.position).normalized;
|
||||
Vector3 fleeTarget = _enemyController.transform.position + fleeDirection * _fleeDistance;
|
||||
|
||||
// 2) 경로 계산해 보기
|
||||
NavMeshPath path = new NavMeshPath();
|
||||
_enemyController.Agent.CalculatePath(fleeTarget, path);
|
||||
_enemyController.Agent.SetDestination(fleeTarget);
|
||||
|
||||
if (path.status == NavMeshPathStatus.PathComplete)
|
||||
{
|
||||
// 제대로 도망갈 수 있으면 목적지 설정
|
||||
_enemyController.Agent.SetDestination(fleeTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 막다른 길임 : 대체 행동 실행
|
||||
HandleDeadEnd();
|
||||
}
|
||||
// 3) 이동
|
||||
_enemyController.Agent.isStopped = false;
|
||||
_fleeSearchTimer = 0;
|
||||
}
|
||||
|
||||
private void HandleDeadEnd()
|
||||
@ -93,16 +113,24 @@ public class EnemyStateFlee :IEnemyState
|
||||
|
||||
if (NavMesh.SamplePosition(randomDirection, out var hit, (_fleeDistance * 2), NavMesh.AllAreas))
|
||||
{
|
||||
// 샘플링에 성공했으면 일단 그 위치로 가 보도록 세팅
|
||||
Debug.Log("## 일단 가봄");
|
||||
_enemyController.Agent.SetDestination(hit.position);
|
||||
return;
|
||||
_enemyController.OnCannotFleeBehaviour();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 대체 경로도 찾을 수 없는 경우
|
||||
Debug.Log("## 대체 경로도 못찾음");
|
||||
_enemyController.OnCannotFleeBehaviour();
|
||||
}
|
||||
|
||||
// 대체 경로도 찾을 수 없는 경우
|
||||
_enemyController.OnCannotFleeBehaviour();
|
||||
}
|
||||
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
_enemyController.Agent.isStopped = true;
|
||||
_enemyController.Agent.ResetPath();
|
||||
_playerTransform = null;
|
||||
_enemyController = null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user