Merge branch 'main' into DEG-54-엔딩-로직
This commit is contained in:
commit
28c72be3b8
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
|
fileFormatVersion: 2
|
||||||
guid: 5b14d6aa88de82f449e47d835ebf73c7
|
guid: 9c16b44c8736e4007ad5f0733ce433e1
|
||||||
PrefabImporter:
|
PrefabImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
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")]
|
[FormerlySerializedAs("housingCanvasManager")]
|
||||||
[Header("UI 연동")]
|
[Header("UI 연동")]
|
||||||
[SerializeField] HousingCanvasController housingCanvasController;
|
[SerializeField] HousingCanvasController housingCanvasController;
|
||||||
|
[SerializeField] private InteractionAnimationPanelController interactionAnimationPanelController;
|
||||||
|
|
||||||
private SuddenEventController _suddenEventController = new SuddenEventController();
|
private SuddenEventController _suddenEventController = new SuddenEventController();
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ public class InteractionController : MonoBehaviour
|
|||||||
if (interactionLayerMask == (interactionLayerMask | (1 << other.gameObject.layer)))
|
if (interactionLayerMask == (interactionLayerMask | (1 << other.gameObject.layer)))
|
||||||
{
|
{
|
||||||
housingCanvasController.HideInteractionButton();
|
housingCanvasController.HideInteractionButton();
|
||||||
|
housingCanvasController.interactionTextsController.InitInteractionTexts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,11 +53,12 @@ public class InteractionController : MonoBehaviour
|
|||||||
if (playerStats.CanPerformByHealth(interactionType))
|
if (playerStats.CanPerformByHealth(interactionType))
|
||||||
{
|
{
|
||||||
playerStats.PerformAction(interactionType);
|
playerStats.PerformAction(interactionType);
|
||||||
|
interactionAnimationPanelController.ShowAnimationPanel(interactionType,interactionTexts.AnimationText);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
housingCanvasController.SetActionText(interactionTexts.LackOfHealth);
|
housingCanvasController.interactionTextsController.ActiveTexts(interactionTexts.LackOfHealth);
|
||||||
housingCanvasController.SetDescriptionText();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
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 System.Collections.Generic;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
public class HousingCanvasController : MonoBehaviour
|
public class HousingCanvasController : MonoBehaviour
|
||||||
{
|
{
|
||||||
[Header("일상행동 상호작용")]
|
[Header("일상행동 상호작용")]
|
||||||
[SerializeField] GameObject interactionButton;
|
[SerializeField] private GameObject interactionButton;
|
||||||
[SerializeField] TMP_Text actionText;
|
public InteractionTextsContoller interactionTextsController;
|
||||||
[SerializeField] TMP_Text descriptionText;
|
|
||||||
|
|
||||||
[Header("돌발 이벤트")]
|
[Header("돌발 이벤트")]
|
||||||
[SerializeField] private GameObject suddenPanel;
|
[SerializeField] private GameObject suddenPanel;
|
||||||
[SerializeField] private TMP_Text suddenText;
|
[SerializeField] private TMP_Text suddenText;
|
||||||
@ -20,34 +20,16 @@ public class HousingCanvasController : MonoBehaviour
|
|||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
InitInteractionTexts();
|
interactionTextsController.InitInteractionTexts();
|
||||||
interactionButton.SetActive(false);
|
interactionButton.SetActive(false);
|
||||||
suddenPanel.SetActive(false);
|
suddenPanel.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 상호작용 일상 행동
|
#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)
|
public void ShowInteractionButton(string actText, string descText,Action onInteractionButtonPressed)
|
||||||
{
|
{
|
||||||
SetActionText(actText);
|
interactionTextsController.ActiveTexts(actText, descText);
|
||||||
SetDescriptionText(descText);
|
|
||||||
interactionButton.SetActive(true);
|
interactionButton.SetActive(true);
|
||||||
|
|
||||||
//각 행동 별로 실행되어야 할 이벤트 구독
|
//각 행동 별로 실행되어야 할 이벤트 구독
|
||||||
@ -56,8 +38,6 @@ public class HousingCanvasController : MonoBehaviour
|
|||||||
//범위에서 벗어나면 상호작용 버튼 off
|
//범위에서 벗어나면 상호작용 버튼 off
|
||||||
public void HideInteractionButton()
|
public void HideInteractionButton()
|
||||||
{
|
{
|
||||||
SetActionText();
|
|
||||||
SetDescriptionText();
|
|
||||||
interactionButton.SetActive(false);
|
interactionButton.SetActive(false);
|
||||||
|
|
||||||
//구독해놓은 이벤트 해제
|
//구독해놓은 이벤트 해제
|
||||||
@ -67,8 +47,13 @@ public class HousingCanvasController : MonoBehaviour
|
|||||||
//상호작용 버튼 눌렀을 때
|
//상호작용 버튼 눌렀을 때
|
||||||
public void OnClickInteractionButton()
|
public void OnClickInteractionButton()
|
||||||
{
|
{
|
||||||
|
//상호작용 별 행동 수행
|
||||||
OnInteractionButtonPressed?.Invoke();
|
OnInteractionButtonPressed?.Invoke();
|
||||||
|
OnInteractionButtonPressed = null;
|
||||||
|
|
||||||
|
//상호작용 버튼과 텍스트 숨김
|
||||||
HideInteractionButton();
|
HideInteractionButton();
|
||||||
|
interactionTextsController.InitInteractionTexts();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
@ -20,10 +20,15 @@ public static class HousingConstants
|
|||||||
public static readonly Dictionary<ActionType, InteractionTexts> interactions =
|
public static readonly Dictionary<ActionType, InteractionTexts> interactions =
|
||||||
new Dictionary<ActionType, InteractionTexts>
|
new Dictionary<ActionType, InteractionTexts>
|
||||||
{
|
{
|
||||||
{ ActionType.Sleep, new InteractionTexts("침대에서 잘까?","숙면으로 시간 당 체력 1을 회복한다.", ".")},
|
{ ActionType.Sleep, new InteractionTexts("침대에서 잘까?","숙면으로 시간 당 체력 1을 회복한다.",
|
||||||
{ ActionType.Housework, new InteractionTexts("밀린 집안일을 처리할까?","체력 1을 사용하고 좋은일이 일어날지도 모른다","힘들어서 못해..")},
|
".","쿨쿨 자는 중")},
|
||||||
{ ActionType.Dungeon, new InteractionTexts("던전에 입장할까?","체력 3을 사용하고 3시간이 흐른다.","던전에 갈 체력이 되지 않아..")},
|
{ ActionType.Housework, new InteractionTexts("밀린 집안일을 처리할까?","체력 1을 사용하고 좋은일이 일어날지도 모른다",
|
||||||
{ ActionType.Work, new InteractionTexts("출근한다.","체력 3을 사용하고 저녁 6시에나 돌아오겠지..", "도저히 출근할 체력이 안되는걸..?")}
|
"힘들어서 못해..","세탁하는 중")},
|
||||||
|
{ ActionType.Dungeon, new InteractionTexts("던전에 입장할까?","체력 3을 사용하고 3시간이 흐른다.",
|
||||||
|
"던전에 갈 체력이 되지 않아..","던전 진입하는 중")},
|
||||||
|
{ ActionType.Work, new InteractionTexts("출근한다.","체력 3을 사용하고 저녁 6시에나 돌아오겠지..",
|
||||||
|
"도저히 출근할 체력이 안되는걸..?","출근하는 중")},
|
||||||
|
{ActionType.Eat, new InteractionTexts("식사를 하자","1시간 동안 체력 1을 회복한다.","밥 먹는 중")}
|
||||||
};
|
};
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -32,12 +37,14 @@ public static class HousingConstants
|
|||||||
public string ActionText { get; private set; }
|
public string ActionText { get; private set; }
|
||||||
public string DescriptionText { get; private set; }
|
public string DescriptionText { get; private set; }
|
||||||
public string LackOfHealth { 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;
|
ActionText = actionText;
|
||||||
DescriptionText = descriptionText;
|
DescriptionText = descriptionText;
|
||||||
LackOfHealth = lackOfHealth;
|
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
|
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()
|
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()
|
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 EnemyController _enemyController;
|
||||||
private Transform _playerTransform;
|
private Transform _playerTransform;
|
||||||
private float _fleeDistance = 5f; // 도망치는 거리
|
private float _fleeDistance = 5f; // 도망치는 거리
|
||||||
private float _attackRange = 7f; // 공격 범위
|
private float _safeRange = 7f; // 공격 범위
|
||||||
|
|
||||||
|
// 경로 탐색 주기 조절용
|
||||||
|
private float _fleeSearchTimer = 0;
|
||||||
|
private float _fleeThresholdTime = 0.2f;
|
||||||
|
|
||||||
// 막다른길 검사용
|
// 막다른길 검사용
|
||||||
private Vector3 _lastPosition;
|
private Vector3 _lastPosition;
|
||||||
@ -21,9 +25,11 @@ public class EnemyStateFlee :IEnemyState
|
|||||||
|
|
||||||
_playerTransform = _enemyController.TraceTargetTransform;
|
_playerTransform = _enemyController.TraceTargetTransform;
|
||||||
_lastPosition = _enemyController.transform.position;
|
_lastPosition = _enemyController.transform.position;
|
||||||
|
|
||||||
|
_enemyController.Agent.ResetPath();
|
||||||
|
_enemyController.Agent.isStopped = false;
|
||||||
_stuckTimer = 0f;
|
_stuckTimer = 0f;
|
||||||
|
_fleeSearchTimer = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
@ -34,8 +40,28 @@ public class EnemyStateFlee :IEnemyState
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float currentDist = Vector3.Distance(
|
||||||
|
_enemyController.transform.position,
|
||||||
|
_playerTransform.position
|
||||||
|
);
|
||||||
|
if (currentDist >= _safeRange)
|
||||||
|
{
|
||||||
|
// 목적지 리셋 후 전투 시작
|
||||||
|
_enemyController.Agent.isStopped = true;
|
||||||
|
_enemyController.Agent.ResetPath();
|
||||||
|
_enemyController.BattleSequence();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FindPositionFlee();
|
FindPositionFlee();
|
||||||
|
|
||||||
|
if (!_enemyController.Agent.pathPending &&
|
||||||
|
_enemyController.Agent.pathStatus == NavMeshPathStatus.PathInvalid)
|
||||||
|
{
|
||||||
|
Debug.Log("## 길을 못찾음");
|
||||||
|
HandleDeadEnd();
|
||||||
|
}
|
||||||
|
|
||||||
// 막힘 감지 (실제 이동 체크)
|
// 막힘 감지 (실제 이동 체크)
|
||||||
CheckPath();
|
CheckPath();
|
||||||
|
|
||||||
@ -44,45 +70,39 @@ public class EnemyStateFlee :IEnemyState
|
|||||||
|
|
||||||
private void CheckPath()
|
private void CheckPath()
|
||||||
{
|
{
|
||||||
float distance = Vector3.Distance(_enemyController.transform.position, _playerTransform.position);
|
float moved = Vector3.Distance(_enemyController.transform.position, _lastPosition);
|
||||||
if (distance < StuckMoveThreshold)
|
if (moved < StuckMoveThreshold)
|
||||||
{
|
{
|
||||||
_stuckTimer += Time.deltaTime;
|
_stuckTimer += Time.deltaTime;
|
||||||
if (_stuckTimer >= StuckThresholdTime)
|
if (_stuckTimer >= StuckThresholdTime)
|
||||||
{
|
{
|
||||||
// 막다른 길임 : 대체 행동 실행
|
|
||||||
|
Debug.Log("## 끼임");
|
||||||
HandleDeadEnd();
|
HandleDeadEnd();
|
||||||
_stuckTimer = 0f;
|
_stuckTimer = 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 정상적인 길: 배틀 루프 실행
|
|
||||||
_enemyController.BattleSequence();
|
|
||||||
_stuckTimer = 0f;
|
_stuckTimer = 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FindPositionFlee()
|
private void FindPositionFlee()
|
||||||
{
|
{
|
||||||
|
_fleeSearchTimer += Time.deltaTime;
|
||||||
|
if (_fleeSearchTimer <= _fleeThresholdTime) return;
|
||||||
|
|
||||||
// 1) 목표 도망 위치 계산
|
// 1) 목표 도망 위치 계산
|
||||||
Vector3 fleeDirection = (_enemyController.transform.position - _playerTransform.position).normalized;
|
Vector3 fleeDirection = (_enemyController.transform.position - _playerTransform.position).normalized;
|
||||||
Vector3 fleeTarget = _enemyController.transform.position + fleeDirection * _fleeDistance;
|
Vector3 fleeTarget = _enemyController.transform.position + fleeDirection * _fleeDistance;
|
||||||
|
|
||||||
// 2) 경로 계산해 보기
|
// 2) 경로 계산해 보기
|
||||||
NavMeshPath path = new NavMeshPath();
|
_enemyController.Agent.SetDestination(fleeTarget);
|
||||||
_enemyController.Agent.CalculatePath(fleeTarget, path);
|
|
||||||
|
|
||||||
if (path.status == NavMeshPathStatus.PathComplete)
|
// 3) 이동
|
||||||
{
|
_enemyController.Agent.isStopped = false;
|
||||||
// 제대로 도망갈 수 있으면 목적지 설정
|
_fleeSearchTimer = 0;
|
||||||
_enemyController.Agent.SetDestination(fleeTarget);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 막다른 길임 : 대체 행동 실행
|
|
||||||
HandleDeadEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleDeadEnd()
|
private void HandleDeadEnd()
|
||||||
@ -93,16 +113,24 @@ public class EnemyStateFlee :IEnemyState
|
|||||||
|
|
||||||
if (NavMesh.SamplePosition(randomDirection, out var hit, (_fleeDistance * 2), NavMesh.AllAreas))
|
if (NavMesh.SamplePosition(randomDirection, out var hit, (_fleeDistance * 2), NavMesh.AllAreas))
|
||||||
{
|
{
|
||||||
|
// 샘플링에 성공했으면 일단 그 위치로 가 보도록 세팅
|
||||||
|
Debug.Log("## 일단 가봄");
|
||||||
_enemyController.Agent.SetDestination(hit.position);
|
_enemyController.Agent.SetDestination(hit.position);
|
||||||
return;
|
_enemyController.OnCannotFleeBehaviour();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 대체 경로도 찾을 수 없는 경우
|
||||||
|
Debug.Log("## 대체 경로도 못찾음");
|
||||||
|
_enemyController.OnCannotFleeBehaviour();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 대체 경로도 찾을 수 없는 경우
|
|
||||||
_enemyController.OnCannotFleeBehaviour();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Exit()
|
public void Exit()
|
||||||
{
|
{
|
||||||
|
_enemyController.Agent.isStopped = true;
|
||||||
|
_enemyController.Agent.ResetPath();
|
||||||
_playerTransform = null;
|
_playerTransform = null;
|
||||||
_enemyController = null;
|
_enemyController = null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user