Kairoengine story system based on the Ink language.
|
2 năm trước cách đây | |
---|---|---|
Editor | 2 năm trước cách đây | |
Prefabs | 2 năm trước cách đây | |
Runtime | 2 năm trước cách đây | |
Tests | 2 năm trước cách đây | |
.gitignore | 2 năm trước cách đây | |
Editor.meta | 2 năm trước cách đây | |
Prefabs.meta | 2 năm trước cách đây | |
Readme.md | 2 năm trước cách đây | |
Readme.md.meta | 2 năm trước cách đây | |
Runtime.meta | 2 năm trước cách đây | |
Tests.meta | 2 năm trước cách đây | |
package.json | 2 năm trước cách đây | |
package.json.meta | 2 năm trước cách đây |
The Story System uses the Ink Language and runtime to navigate through a story written in a plain text file. This package contains the Story Module that receives an ink story and runs it. The story can show lines and branches, execute functions in unity and wait for events. Unity also has an API for navigating, getting and setting variables in the story.
KairoEngine.Core
KairoEngine.UI
Ink
UniRX
TextMeshPro
Sirenix
KairoEngine.StorySystem
KairoEngine.StorySystem.UI
KairoEngine.StorySystem.EditorTests
StoryViewUI
– A generic UI for showing text and buttons based on story events.StoryButton
– A button used in the Story View UIStoryText
– A text object used in the Story View UITo get started using the Story module, first add it to a game config and add an installer prefab to a scene. Then install [Inky](), the Ink editor. Create a new Ink story, save the file and add it to the Unity project. Unity will generate a JSON file from the Ink file then add it the story module configuration.
A simple example Ink story:
Once upon a time...
* There was a choice.
* There was another choice.
- And they lived happily ever after.
-> END
When this story is run on Unity after been loaded with the story module, it will read the first line and send it as an event to the game. Then it will read all choices and send them as a single event to the game. The story system will wait for another event containing the chosen path. The system will then send an event containing the last line of text in the story and then will stop.
The story system publishes events containing StoryStepData
that other scripts can subscribe to. This object contains data about that passage of the story. It can be a line of text, a list of choices or a integer for the path that has been selected.
When the Ink story runs, lines and branches will be sent as events imidiatly in order. Wait functions can delay that process. Once a branch has been reached, the story will wait for an event to be sent back containing the selected path.
Below, in the Unity Functions section there are instructions on how to send and receive story events with code examples.
Use these functions in an Ink document to execute things in Unity. Each function has a usage pattern and the actual function that needs to go somewhere inside the Ink document.
Make the story wait for a certain amount of time. In the Ink story file, use ~Wait(time)
anywhere in the story to make unity wait the amout of time before continuing the story.
// Example Usage
Something happens
~ Wait(3000)
After three seconds another thing happens
Add the functions below for declaring a external function to Ink and a fallback function to make it work in the Inky editor
EXTERNAL WaitForTime(time)
=== function Wait(time) ===
~WaitForTime(time)
<> <i>(Wait {time} ms)</i>
=== function WaitForTime(time) ===
~x = ""
Enable and disable GameObjects. In Ink, use ~Enable("StoryGameObjectName")
or ~ Disable("StoryGameObjectName")
. Add prefabs for the GameObjects used in the story to the list on the Story Module config.
// Show a menu in the game and close it after the choice is made
~ Enable("MainMenuUI")
Main Menu
+ [Start Game]
~ Disable("MainMenuUI")
-> StartGame
+ [End Game]
~ Disable("MainMenuUI")
-> END
Add the function below anywhere on the ink document:
EXTERNAL Enable(name)
EXTERNAL Disable(name)
=== function Enable(name) ===
> Enable <i>{name}</i>
=== function Disable(name) ===
> Disable <i>{name}</i>
Triggers a GenericEvent
in unity. Pass in a string containing the name of the event to be triggered. Example:
~ TriggerEvent("MyCustomEvent")
EXTERNAL TriggerEvent(name)
=== function TriggerEvent(name) ===
> Trigger event "<i>{name}</i>"
These are functions used in Unity to change and navigate a Ink story. Also there are helper function for doing various things like observers and events.
To receive story events, simply subscribe to events with the story name and a function.
EventManager.broadcast.StartListening(storyName, OnStoryStep);
The function for these events needs to receive story step data, for example:
void OnStoryStepData(StoryStepData storyStep)
{
Debug.Log($"> {storyStep.text}");
}
Don't forget to stop listening for events when the script is done. For example, using a monobehaviour derived class:
void OnDisable()
{
EventManager.broadcast.StopListening(storyName, OnStoryStep);
}
When the story has reached a branch, it will wait ultil it receives an event containing the selected path.
int path = 0;
StoryStepData storyStep = new StoryStepData(StoryStepType.Path, text, null, null, path)
EventManager.broadcast.Trigger(storyName, storyStep )
Instead of declaring delegates using events, it's possible to subscribe to story steps using observers:
CompositeDisposable composite = new CompositeDisposable();
// Subscribe to the custom observer
// Other UniRX functions can be chained here
StoryController.Lines().Subscribe(storyStep => {
Debug.Log(storyStep.text);
// Stop the observer
composite.Dispose()
}).AddTo(composite);
The Story Controller Lines observer requires the kairoEngine.StorySystem
namespace.