Extends dialogue panels module

Add multi-threading dialogue system
This commit is contained in:
kabix09 2022-12-02 02:11:37 +01:00
parent e88668415e
commit fb692e1bb8
7 changed files with 394 additions and 29 deletions

View File

@ -188,6 +188,141 @@ MonoBehaviour:
m_StringArgument: m_StringArgument:
m_BoolArgument: 0 m_BoolArgument: 0
m_CallState: 2 m_CallState: 2
CurrentDialogue: 0
MultiWayDialogue:
- Key: 0
Value:
- WasDisplayed: 0
ListOfSentences:
- Sentence: test
Buttons: []
- Sentence: test 1.1
Buttons:
- ButtonName: Ok
Type: 1
ButtonActions:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 5064228440392526989}
m_TargetAssemblyTypeName: NpcDialogueManager, Assembly-CSharp
m_MethodName: GoToNextSentence
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 1
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
Rewards: []
EndOfDialogueStepAction:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 5064228440392526989}
m_TargetAssemblyTypeName: NpcDialogueManager, Assembly-CSharp
m_MethodName: TestEndAction
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
- WasDisplayed: 0
ListOfSentences:
- Sentence: test 1.2
Buttons: []
- Sentence: test 1.2.3
Buttons:
- ButtonName: way 1.2
Type: 1
ButtonActions:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 5064228440392526989}
m_TargetAssemblyTypeName: NpcDialogueManager, Assembly-CSharp
m_MethodName: SetNextDialogue
m_Mode: 3
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 1
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
Rewards: []
EndOfDialogueStepAction:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 482428332992622001}
m_TargetAssemblyTypeName: BossThug, Assembly-CSharp
m_MethodName: BreakConversation
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
- Key: 1
Value:
- WasDisplayed: 0
ListOfSentences:
- Sentence: test 2
Buttons:
- ButtonName: test 2.1 ans
Type: 1
ButtonActions:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 5064228440392526989}
m_TargetAssemblyTypeName: NpcDialogueManager, Assembly-CSharp
m_MethodName: GoToNextSentence
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
- Sentence: test 2.1
Buttons: []
Rewards: []
EndOfDialogueStepAction:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 482428332992622001}
m_TargetAssemblyTypeName: BossThug, Assembly-CSharp
m_MethodName: ChanegStatusToAttack
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
- m_Target: {fileID: 482428332992622001}
m_TargetAssemblyTypeName: BossThug, Assembly-CSharp
m_MethodName: SetEndConversation
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &482428332992622006 --- !u!114 &482428332992622006
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -245,7 +380,8 @@ MonoBehaviour:
animator: {fileID: 0} animator: {fileID: 0}
newController: {fileID: 0} newController: {fileID: 0}
isAfterConversation: 0 isAfterConversation: 0
state: 0 isDuringConversation: 0
state: 1
--- !u!95 &-4365747932373452915 --- !u!95 &-4365747932373452915
Animator: Animator:
serializedVersion: 3 serializedVersion: 3

View File

@ -50,18 +50,27 @@ public class DialogueController
{ {
Panel panelDis = panelModel.Panel("Kabix", panelModel); Panel panelDis = panelModel.Panel("Kabix", panelModel);
panelDis.PanelInstance = panelDis.BuildPanel(); panelDis.PanelInstance = panelDis.BuildPanel();
panelDis.SetContinueButtonAction(ShowNextPanel, this);
if(!(panelDis is QuestionPanel))
panelDis.SetContinueButtonAction(ShowNextPanel, this);
CurrentPanel = panelDis.PanelInstance; CurrentPanel = panelDis.PanelInstance;
} }
/// <summary>
private void ShowNextPanel(DialogueController parentDialController) /// Return false if there was no more 'sentences' in current 'step'
/// </summary>
/// <param name="parentDialController"></param>
/// <returns></returns>
public bool ShowNextPanel(DialogueController parentDialController)
{ {
Debug.Log(listOfDialogue.Count);
if (listOfDialogue.Count == 0) if (listOfDialogue.Count == 0)
{ {
MonoBehaviour.Destroy(parentDialController.CurrentPanel); CloseCurrentPanel(parentDialController);
FinishDialogue(); FinishDialogue();
return false;
} }
else else
{ {
@ -71,6 +80,18 @@ public class DialogueController
Show(nextPanel); Show(nextPanel);
} }
return true;
}
public void CloseCurrentPanel(DialogueController parentDialController)
{
MonoBehaviour.Destroy(parentDialController.CurrentPanel);
}
public void CloseCurrentPanel()
{
MonoBehaviour.Destroy(CurrentPanel);
} }
// if palyer click last dialogue panel's "continue" button then ShowNextPanel // if palyer click last dialogue panel's "continue" button then ShowNextPanel

View File

@ -10,7 +10,7 @@ public static class PanelComponentFactory
/// <param name="size"></param> /// <param name="size"></param>
/// <param name="scale"></param> /// <param name="scale"></param>
/// <returns></returns> /// <returns></returns>
public static GameObject BuildCustomPanel(Vector3 position, Vector2 size, Vector3 scale) public static GameObject BuildCustomPanel(Vector3 position, Vector2 size, Vector3 scale, bool withContinue = true)
{ {
var panel = DialoguePanelsPrefabsList.GetPanel(); var panel = DialoguePanelsPrefabsList.GetPanel();
@ -24,12 +24,20 @@ public static class PanelComponentFactory
prefab.transform.SetParent(GameObject.FindGameObjectWithTag("GUI").transform, false); prefab.transform.SetParent(GameObject.FindGameObjectWithTag("GUI").transform, false);
GameObject continueButton = BuildContinueButton(new Vector3(-100, 150, 0), new Vector2(115, 90), new Vector3(1.2f, 1.2f, 1));
continueButton.transform.SetParent(prefab.transform, false);
return prefab; return prefab;
} }
public static GameObject BuildCustomPanelWithContinue(Vector3 position, Vector2 size, Vector3 scale)
{
var panel = BuildCustomPanel(position, size, scale);
GameObject continueButton = BuildContinueButton(new Vector3(-100, 150, 0), new Vector2(115, 90), new Vector3(1.2f, 1.2f, 1));
continueButton.transform.SetParent(panel.transform, false);
return panel;
}
public static GameObject BuildCustomButton(ButtonPanelModel answerModel) public static GameObject BuildCustomButton(ButtonPanelModel answerModel)
{ {
var panel = DialoguePanelsPrefabsList.GetBaseButton(); var panel = DialoguePanelsPrefabsList.GetBaseButton();

View File

@ -17,6 +17,16 @@ public class Panel : AbstractPanel
public Panel(Vector3 _position, Vector2 _size, Vector3 _scale) : base (_position, _size, _scale){ } public Panel(Vector3 _position, Vector2 _size, Vector3 _scale) : base (_position, _size, _scale){ }
public override GameObject BuildPanel() public override GameObject BuildPanel()
{
GameObject panelPrefab = PanelComponentFactory.BuildCustomPanelWithContinue(Position, Size, Scale);
panelPrefab.transform.Find("Header").gameObject.GetComponent<UnityEngine.UI.Text>().text = Header;
panelPrefab.transform.Find("Content").gameObject.GetComponent<UnityEngine.UI.Text>().text = Content;
return panelPrefab;
}
public GameObject BuildPanelWithoutContinue()
{ {
GameObject panelPrefab = PanelComponentFactory.BuildCustomPanel(Position, Size, Scale); GameObject panelPrefab = PanelComponentFactory.BuildCustomPanel(Position, Size, Scale);
@ -26,7 +36,7 @@ public class Panel : AbstractPanel
return panelPrefab; return panelPrefab;
} }
public void SetContinueButtonAction(Action<DialogueController> onClickFunction, DialogueController dialogControllerModel) public void SetContinueButtonAction(Func<DialogueController, bool> onClickFunction, DialogueController dialogControllerModel)
{ {
PanelInstance.transform.Find("ContinueButton").GetComponent<Button>().onClick.AddListener(() => onClickFunction(dialogControllerModel)); PanelInstance.transform.Find("ContinueButton").GetComponent<Button>().onClick.AddListener(() => onClickFunction(dialogControllerModel));
} }

View File

@ -16,7 +16,7 @@ public class QuestionPanel : Panel
public override GameObject BuildPanel() public override GameObject BuildPanel()
{ {
var questionPanel = base.BuildPanel(); var questionPanel = BuildPanelWithoutContinue();
foreach (ButtonPanelModel answerModel in Answers) foreach (ButtonPanelModel answerModel in Answers)
{ {

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEngine; using UnityEngine;
[Serializable] [Serializable]
@ -9,6 +10,26 @@ public class NpcDialogueManager : MonoBehaviour
[SerializeField] [SerializeField]
public List<DialogueStepModel> DialogueStepsList; public List<DialogueStepModel> DialogueStepsList;
[SerializeField]
int CurrentDialogue = 0;
[SerializeField]
public List<IndexValuePair<int, List<DialogueStepModel>>> MultiWayDialogue;
/*
Dialogues - list of dialoges
Steps bucket (one dialogue unit) - list of liner 'steps', finished special action, whole can be stopped special requirements (like go and do something - to declared in 'finish action')
Steps - its a cell package contains 'sentences' (one per panel)
Sentence - its a opanel with phrase and buttons
*/
/*
* WAZNE:
* Jesli przechodzimy odpowiedzia do nastepnego dialogu musi to byc osttani panel w obecnym!!!
*/
public void Start() public void Start()
{ {
/* CODE DIALOGUE DECLARATION EXAMPLE /* CODE DIALOGUE DECLARATION EXAMPLE
@ -26,27 +47,135 @@ public class NpcDialogueManager : MonoBehaviour
DialogueStepsList = new List<DialogueStepModel> { dialogueStepModel }; DialogueStepsList = new List<DialogueStepModel> { dialogueStepModel };
*/ */
if(MultiWayDialogue.Count > 0)
BuildDialogue(); BuildDialogue(MultiWayDialogue.Where(el => el.Key == CurrentDialogue).First().Value);
} }
/// <summary> public void StartDialogue()
/// Function to begin dialogue - will be invoked after user reaction from other script :) {
/// </summary> // 1. Build
public void ShowStep() BuildDialogue(MultiWayDialogue.Where(el => el.Key == CurrentDialogue).First().Value);
// 2. Show first step
ShowStep();
}
public void BreakDialogue()
{ {
// 1. Find first yet undisplayed for player anbd show // 1. Find first yet undisplayed for player anbd show
foreach(var DialogueStep in DialogueStepsList)
DialogueStepsList = MultiWayDialogue.Where(el => el.Key == CurrentDialogue).ToArray().First().Value;
foreach (var DialogueStep in DialogueStepsList)
{ {
if(!DialogueStep.WasDisplayed && DialogueStep.DialogueController.listOfDialogue.Count != 0) if (!DialogueStep.WasDisplayed && DialogueStep.DialogueController.listOfDialogue.Count != 0)
{ {
DialogueStep.DialogueController.Show(DialogueStep.DialogueController.listOfDialogue.Dequeue()); DialogueStep.DialogueController.CloseCurrentPanel(); // close panel
break; break;
} }
} }
} }
/// <summary>
/// Dialogue API
///
/// MAIN bunction to begin dialogue
/// Create new panel instance on scene by force with sentence from queue
///
/// The best way is to invoked its after player reaction from other script (by event - collision) :)
/// </summary>
public void ShowStep()
{
// 1. Find first yet undisplayed for player anbd show
DialogueStepsList = MultiWayDialogue.Where(el => el.Key == CurrentDialogue).ToArray().First().Value;
foreach (var DialogueStep in DialogueStepsList)
{
if(!DialogueStep.WasDisplayed && DialogueStep.DialogueController.listOfDialogue.Count != 0)
{
DialogueStep.DialogueController.Show(DialogueStep.DialogueController.listOfDialogue.Dequeue()); // create panel
break;
}
}
}
/// <summary>
/// Dialogue API
///
/// Default function to get next sentence if dialogue is currently started
/// It is responsible for detecting
/// 1) if there is any dialogue panel already created before displaying next sentence
/// 2) if its last panel sentence and invoiking 'end dialogue' action
///
/// Whats more, if there was no more sentences in 'step', althroughr closing panel go to next step automatiiccally
/// </summary>
public void GoToNextSentence()
{
// 1. Find first yet undisplayed for player anbd show
DialogueStepsList = MultiWayDialogue.Where(el => el.Key == CurrentDialogue).ToArray().First().Value;
foreach (var DialogueStep in DialogueStepsList)
{
if (!DialogueStep.WasDisplayed)
{
var nextSentence = DialogueStep.DialogueController.ShowNextPanel(DialogueStep.DialogueController);
if (!nextSentence)
{
DialogueStep.WasDisplayed = true;
ShowStep();
}
break;
}
}
}
/// <summary>
/// Dialogue API
///
/// Function to prepare next dialogue to start after one more palyer interaction with actor
/// - ends current dialogue (destroy panel & invoke finish action - if setupped)
/// - set new dialogue pointer
///
/// </summary>
/// <param name="dialogueNumber"></param>
public void SetNextDialogue(int dialogueNumber)
{
if (MultiWayDialogue.Where(el => el.Key == dialogueNumber).ToArray().Count() == 0)
return;
// 1. Make sure to close current panel after finishing current dialogue and 'finish action' will invoked if setuped
GoToNextSentence();
// 2. Chane index
CurrentDialogue = dialogueNumber;
}
/// <summary>
/// Dialogue API
///
/// Function to finish current dialog and immediately start next one
///
/// </summary>
/// <param name="dialogueNumber"></param>
public void GoToNextDialogue(int dialogueNumber)
{
// 1. Prepare necessary environoment parts
SetNextDialogue(dialogueNumber);
// 3. Build new dialogue
BuildDialogue(MultiWayDialogue.Where(el => el.Key == CurrentDialogue).First().Value);
// 4. Start new dialogue bucket
ShowStep();
}
/// <summary> /// <summary>
/// Build each step of dialogue /// Build each step of dialogue
/// </summary> /// </summary>
@ -57,4 +186,20 @@ public class NpcDialogueManager : MonoBehaviour
dialogueStep.Build(); dialogueStep.Build();
} }
} }
/// <summary>
/// Build each step of dialogue
/// </summary>
private void BuildDialogue(List<DialogueStepModel> Dialogue)
{
foreach (var dialogueStep in Dialogue)
{
dialogueStep.Build();
}
}
public void TestEndAction()
{
Debug.Log("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh");
}
} }

View File

@ -23,7 +23,7 @@ public class BossThug : MonoBehaviour
public RuntimeAnimatorController newController; public RuntimeAnimatorController newController;
public bool isAfterConversation = false; // drop it if you can... public bool isAfterConversation = false; // drop it if you can...
public bool isDuringConversation = false;
public BossThugEnum state = BossThugEnum.Pending; public BossThugEnum state = BossThugEnum.Pending;
// Start is called before the first frame update // Start is called before the first frame update
@ -77,6 +77,9 @@ public class BossThug : MonoBehaviour
private void ActivateKillingMode() private void ActivateKillingMode()
{ {
// set lower radious in order to less attack distance
gameObject.GetComponent<CircleCollider2D>().radius = 2f;
gameObject.GetComponent<FollowingEnemy>().enabled=true; gameObject.GetComponent<FollowingEnemy>().enabled=true;
animator.runtimeAnimatorController = Resources.Load("SampleScene/Enemies/BossThugAnimator.controller") as RuntimeAnimatorController; animator.runtimeAnimatorController = Resources.Load("SampleScene/Enemies/BossThugAnimator.controller") as RuntimeAnimatorController;
gameObject.GetComponent<FollowingEnemy>().baseAttack=1000f; gameObject.GetComponent<FollowingEnemy>().baseAttack=1000f;
@ -84,7 +87,7 @@ public class BossThug : MonoBehaviour
private void ActivateDialogueMode() private void ActivateDialogueMode()
{ {
gameObject.GetComponent<CircleCollider2D>().radius = 5f; gameObject.GetComponent<CircleCollider2D>().radius = 4f;
} }
public void ChanegStatusToAttack() public void ChanegStatusToAttack()
@ -92,18 +95,60 @@ public class BossThug : MonoBehaviour
state = BossThugEnum.Attacking; state = BossThugEnum.Attacking;
} }
public void OnTriggerStay2D(Collider2D other)
public void OnTriggerEnter2D(Collider2D other)
{ {
//Debug.Log("kill"); if (other.tag == "Player" && state == BossThugEnum.Talking && !isAfterConversation && !isDuringConversation)
if(other.tag == "Player" && state == BossThugEnum.Talking && !isAfterConversation)
{ {
isAfterConversation = true;
gameObject.GetComponent<CircleCollider2D>().enabled = false; //gameObject.GetComponent<CircleCollider2D>().enabled = false;
gameObject.GetComponent<CircleCollider2D>().radius = 2f; //gameObject.GetComponent<CircleCollider2D>().radius = 2f;
gameObject.GetComponent<NpcDialogueManager>().ShowStep(); isDuringConversation = true;
gameObject.GetComponent<NpcDialogueManager>().StartDialogue();
} }
} }
public void OnTriggerStay2D(Collider2D other)
{
if (other.tag == "Player" && state == BossThugEnum.Talking && !isAfterConversation && !isDuringConversation)
{
isDuringConversation = true;
gameObject.GetComponent<NpcDialogueManager>().StartDialogue();
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.tag == "Player" && state == BossThugEnum.Talking && !isAfterConversation && isDuringConversation)
{
Debug.Log("break dialogue");
//gameObject.GetComponent<CircleCollider2D>().enabled = true;
//gameObject.GetComponent<CircleCollider2D>().radius = 2f;
isDuringConversation = false;
gameObject.GetComponent<NpcDialogueManager>().BreakDialogue();
//TODO break dialogue after leaving collider range!!!
}
}
/// <summary>
/// Set as action invoked in event after 'NpcDialogueManager::SetNextDialogue()' function to adjust Trigger2D event listening
/// </summary>
public void BreakConversation()
{
isDuringConversation = false;
}
public void SetEndConversation()
{
isAfterConversation = true;
}
} }