Chinese psychic Theme

Westward journey:
An RPG with AIGC

Key words: video games, game design, AI, AI-generated narrative, user generated content (UGC)

An AIGC Narrative Game

Abstract

This study delves into using AI in the narrative design of a 2D RPG centered on fortune-telling. The game stands out for departing from traditional narrative methods, employing AI to craft evolving storylines based on player choices. This integration offers an immersive and exploratory experience, granting players greater autonomy in shaping the game’s outcome. However, ethical concerns arise regarding the influence on player behavior and decision-making. The research explores a design approach for implementing AI-generated content in video games through practice-based research.

AIGC

Dialogue System (User Generated)

Video Showcase

Research Topics

01

game Narrative

Historically-based fictional narratives in video games

02

AI generated Content

Explore a Design Approach of AI-generated Content for Video Games

Inspirations

User Interface

Game Flow

Step 01:

You are a psychic! Engage with your client to discover their stories and needs.

Step 02:

Choose a proper tool to divine their future.

Step 03:

Analyze the results with your instruction.

Step 04:

Craft a reply for your client.

Finally, await the outcome in the next few "days"!

Your client will write a mail back (AI generated based on your suggestion) to tell you where the story goes.

Technical foundation

How It Work?

Use Open AI’s application programming interface (API)

Vertical Slices

Note: The Vertical Slice is a complete cross-section of the final game and its purpose is to convince stakeholders, such as publishers and investors, to continue funding the game’s development.

 
 
Prototype in Twine
 
Firstly, I used Twine, a tool that supports scripting language and creates visual novels through node-based connections to dynamically showcase different story scenes. In game development, POCG is often done through paper prototypes, but since I’m creating a text-based RPG, Twine is a suitable tool for prototyping and iteration.
 
Scripts Sample
 
 
The Challenge of the Game!
 
The biggest challenge in games comes from the unknown outcome. The outcome of divination should never be predetermined by the designer, so we introduced Open AI to continue the story, with unexpected endings from time to time!
 
 
AI Writes the Story Ending: 
 
  1. Prompt Framework (The Message Sent to Chat gpt)
“Write a mail back to the psychic with an unexpected ①extremely bad ending to the following story in realism ②in the perspective of Mila (7-year-old little girl): ③Mila is a little girl who one day can’t find her favourite doll. The doll was left to her by her brother, who died in the war, and was actually washed by her mother and hung up on the balcony to dry. She searched everywhere but to no avail, and finally undertook a divination. ④The divination suggested that she could go to the nearby river to look for it. What would be the outcome for her?”
 
①extremely bad ending: a good/bad ending will be influenced by the player’s behaviour.
②in the perspective of Mila: the perspective of NPCs.
③Mila is……: background of NPCs.
④The divination suggested……: The content will be the text that the player typed in the chat box after the mini game.
 
  1. Send to Chat gpt
Through the API, Unity could send this message to Chat gpt and get the reply (specific scripts are on the next section).
 
  1. Get reply and deliver to the player
Finally, Unity will receive a reply from Chat gpt!
Text:
Dear Psychic,
 
Thank you for assisting Mila in finding her doll. According to the divination, she went to the nearby river to look for it, but unfortunately the outcome was not positive.
 
Mila arrived at the river and, despite searching for hours, never found her beloved doll. She was so disappointed that she decided to take a rest by the river bank and closed her eyes in sadness. Suddenly, she heard a loud thud. When she opened her eyes, she saw the water had suddenly risen and the riverbank was completely flooded. Soon enough, Mila realized what had happened – the doll, which had been washed by her mother and left on the balcony to dry, had blown away in the wind and ended up in the river. She had arrived too late.
 
Although Mila will never get her beloved doll back, I hope that with time and with your help, she will learn to cope with her loss and find peace.
 
Sincerely,
Mila’s mom
 
Use API to Implement Open AI (Chat gpt) in Unity
 
These are the specific scripts that how I implement this function:
        public void SendData(string question)
    {
        StartCoroutine (GetPostData (question,CallBack));
    }
    
        private IEnumerator GetPostData(string _postWord,System.Action<string> _callback)
        {
                var request = new UnityWebRequest (m_ApiUrl, "POST");
                PostData _postData = new PostData
                        {
                                model = m_PostDataSetting.model,
                                prompt = _postWord,
                                max_tokens = m_PostDataSetting.max_tokens,
                                temperature=m_PostDataSetting.temperature,
                                top_p=m_PostDataSetting.top_p,
                                frequency_penalty=m_PostDataSetting.frequency_penalty,
                                presence_penalty=m_PostDataSetting.presence_penalty,
                                stop=m_PostDataSetting.stop
                        };
                string _jsonText = JsonUtility.ToJson (_postData);
                byte[] data = System.Text.Encoding.UTF8.GetBytes (_jsonText);
                request.uploadHandler = (UploadHandler)new UploadHandlerRaw (data);
                request.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer ();
 
                request.SetRequestHeader ("Content-Type","application/json");
                request.SetRequestHeader("Authorization",string.Format("Bearer {0}",m_OpenAI_Key));
                yield return request.SendWebRequest ();
                if (request.responseCode == 200) {
                                string _msg = request.downloadHandler.text;
                                TextCallback _textback = JsonUtility.FromJson<TextCallback> (_msg);
                                if (_textback!=null && _textback.choices.Count > 0) {
                                        _callback(_textback.choices [0].text);
                                }
                }
        }
}

[System.Serializable]public class TextCallback{
                public string id;
                public string created;
                public string model;
                public List<TextSample> choices;
                [System.Serializable]public class TextSample{
                        public string text;
                        public string index;
                        public string finish_reason;
                }
        }
Prompt Design
 
Here are some factors that may help AI to write the content in an ideal direction:
Factors
Examples
Story background
“Mila is a little girl who one day can’t find her favourite doll. The doll was left to her by her brother, who died in the war, and was actually washed by her mother and hung up on the balcony to dry.”
“Radoslav is a retired soldier. Although he wanted very much to return to the army, he was unable to return to combat because of his physical disability. He is currently working as a bodyguard for a private investigator, but he thinks his life is too meaningless.”
Narrative tone
From Mila’s perspective
From the perspective of Mila’s mom
From a journalist’s point of view
Parameterization
Good ending
Bad ending
Realism
Fantasism
apathetic
emotional
unconventional
In this vertical slice, I have completed the basic framework of the program.
 
Scripts
I will control the game framework through three scripts:
 
 
Character Movement System
 
Currently, role movement and collision detection have been implemented. Now players can freely manipulate the characters to explore the scene!
 
Collision Detection and Event Control
 
After interacting with the NPC (the red block), the player can enter the door (the blue block) and trigger the “start divination” event.
 
Game Flow
 
Inspiration
 
 
Palmistry, also known as chiromancy, is the art of interpreting the lines, shapes, and other features of the hands to gain insight into a person’s character and future. The practice is believed to have originated in ancient India and has been used for centuries across many cultures.
 
Palmistry involves examining the lines on the palm, including the heart line, head line, and life line, as well as the shape and size of the palm and fingers. Each line and feature is said to represent different aspects of a person’s life, such as their emotional state, career path, and relationships.
 
While some people view palmistry as a form of fortune telling, others see it as a tool for self-reflection and personal growth. It is important to note that palmistry should not be used as a substitute for professional advice or medical diagnosis.
 
I refer to the setting of this article: there are four main lines on the human hand, which are hand line, head line, health line and heart line. Then, I designed the mechanism:
 
Observe one of four lines on an NPC’s hand and find the appropriate node on a 12-year timeline to get information. The NPC places the hand under a lens (magnifying glass), and the player has to choose one of four lines to observe (the heartline, the headline, the lifeline and the fateline). After the selection, take 12 years as the time span, click and move the mouse to switch the time node. The player has to find the appropriate node, consult the palm guide, and then get the information.
 
Code
Name
Code
PalmistryManeger.cs
public class PalmistryManager : MonoBehaviour
{
    public GameObject[] Palms;
    public GameObject[] HeartsLine;
    public GameObject[] HeadLine;
    public GameObject[] HealthLine;
    public static PalmistryManager Instance;

    private int index;
    public enum PALM_LINE_TYPE
    {
        HEARTS,
        HEALTH,
        HEAD,
    }

    private void Awake()
    {
        if (Instance == null) Instance = this;
    }

    public void HandleLinesActivated(PALM_LINE_TYPE type)
    {
        HandleResetLines();
        switch (type)
        {
            case PALM_LINE_TYPE.HEARTS:
                HeartsLine[index].SetActive(true);
                break;
            case PALM_LINE_TYPE.HEALTH:
                HealthLine[index].SetActive(true);
                break;
            case PALM_LINE_TYPE.HEAD:
                HeadLine[index].SetActive(true);
                break;
        }

    }

    private GameObject findPalmBaseOnName(string name)
    {
        for(int i = 0;i<Palms.Length;i++)
        {
            if (Palms[i].name == name)
            {
                index = i;
                return Palms[i];
            }
        }
        index = -1;
        return null;
    }

    public void HandleActivePalmistry(string playerName)
    {
        GameObject obj = findPalmBaseOnName(playerName);
        if(obj!=null)
        {
            obj.SetActive(true);
        }
    }
}
Game Flow
 
 
Inspiration
The Chinese fortune-telling method known as “counting bones” or “fortune-telling with sticks” is an ancient practice that dates back to the Zhou dynasty. This method involves using a set of 100 bamboo sticks or bones engraved with numbers and symbols to predict a person’s future. To start the process, the fortune teller will ask the person to think of a question or issue they would like guidance on. The person will then shake the container holding the sticks until one falls out. This stick is then matched to a corresponding interpretation in a book or chart.
The interpretation of the stick reading is based on a combination of the number and symbol engraved on the stick, as well as the person’s birth date and other factors. The fortune teller will use this information to provide insight into the person’s future and offer guidance on how to navigate challenges or make important decisions. While some people view “counting bones” as a form of superstition, it is still widely practiced in many parts of China and is considered a valuable tool for gaining insight and guidance.
 
 
Formula Example (in Chinese)
I simplified the table in English to make it more suitable for games. Otherwise, the game will become a purely computational process, which is not cool for players (and may cause a large percentage of players to lose interest).
 
Code
Name
Code
Weights
public class Weights : MonoBehaviour
{
    public int weight;
    private void OnTriggerEnter(Collider other)
    {
        if(other.tag == "BIN")
        {
            WeightsManager.Instance.HandleCurrentWeightMoveToBin();
        }
    }
}
Weights Manager
 public class WeightsManager : MonoBehaviour
{
    public static WeightsManager Instance;
    public GameObject WEIGHTA;
    public GameObject WEIGHTB;
    private bool isHoldingWeight;
    private bool forceReleaseWeight;
    private GameObject currentHoldingWeight;

    void Update()
    {
        if(Input.GetMouseButton(0))
        {
            if(!isHoldingWeight && !forceReleaseWeight)
            {
                RaycastHit hit;
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                if(Physics.Raycast(ray,out hit))
                {
                    GameObject prefabToUse = null;
                    if(hit.collider.CompareTag("WEIGHTAMASTER"))
                    {
                        prefabToUse = WEIGHTA;
                    }
                    else if(hit.collider.CompareTag("WEIGHTBMASTER"))
                    {
                        prefabToUse = WEIGHTB;
                    }
                    else if(hit.collider.CompareTag("WEIGHTA")||hit.collider.CompareTag("WEIGHTB"))
                    {
                        currentHoldingWeight = hit.transform.gameObject;
                        isHoldingWeight = true;
                    }
                    if(prefabToUse!=null)
                    {
                        currentHoldingWeight = Instantiate(prefabToUse);
                        currentHoldingWeight.transform.SetParent (this.gameObject.transform);
                        currentHoldingWeight.transform.localScale = new Vector3(1, 1, 1);
                        isHoldingWeight = true;
                    }
                }
            }
            else if(isHoldingWeight)
            {
                currentHoldingWeight.GetComponent<RectTransform>().localPosition = new Vector3(Input.mousePosition.x - Screen.width / 2, Input.mousePosition.y - Screen.height / 2, 0);
            }
        }
    }
}
Game Flow
 
 
Inspiration
Burning incense, also known as fragrance or aroma therapy, is a traditional practice in many cultures around the world. Incense is made of various natural ingredients, such as herbs, spices, flowers, and resins, that are ground and blended together to create a scented mixture. When ignited, the mixture releases a fragrant smoke that is believed to have healing and purifying properties, and is used for spiritual, religious, and therapeutic purposes.
 
Chinese Incense:
https://www.bilibili.com/video/BV1cW411o756/?spm_id_from=333.337.search-card.all.click&vd_source=22b825dd0ccf33726a292c0709292a55
 
The setting of this game is not based on reality. I introduced the concept of burning incense to build a virtual game:
 
  • Burn different materials with different attributes to get the right timing for an NPC’s age and receive a fortune message:
Players have four materials to burn:
  Fire property, time x 2, 10¥
  Wood property, time + 5, 5¥
  Gold attribute, time +3, 3¥
  Water properties, time – 1, 2¥
  The results need to be based on the order in which the materials were added. For example, 1 wood +1 gold +1 fire +1 water = (5+3) x 2-1=15. Players need to spend as little as possible while keeping the timing right.
 
Code
Name
Code
IncenseManager.cs
public class IncenseManager : MonoBehaviour
{
    public int TotalValue;
    public int TotalSpend;
    public GameObject TargetAgeText;
    public GameObject FailBark;
    public GameObject[] Success;


    private bool isFadeIn;
    private bool isFadeOut;
    private int index;
    private GameObject CurrentObj;
    public static IncenseManager Instance;
    public enum ELEMENTS
    {
        FIRE,
        WOOD,
        GOLD,
        WATER,
    }

    private GameObject findSuccessBaseOnName(string name)
    {
        for(int i = 0;i<Success.Length;i++)
        {
            if (Success[i].name == name)
            {
                index = i;
                return Success[i];
            }
        }
        index = -1;
        return null;
    }


    void Start()
    {
        Reset();
        index = 0;
    }
    private void CheckResult()
    {
        if(TotalValue == PsychicManager.Instance.GetCurrentTargetCharacter().GetComponent<BaseCharacter>().Age && TotalSpend <= PsychicManager.Instance.GetCurrentTargetCharacter().GetComponent<BaseCharacter>().Money)
        {
            print("Success!");//success
            StartCoroutine(HandleSuccessFade());
        }
        else
        {
            print("Fail!");
            HandleFail();
            Reset();
        }
    }


     IEnumerator HandleSuccessFade()
    {
        isFadeIn = true;
        isFadeOut = false;
        yield return new WaitForSeconds(2.5f);
        index++;
        isFadeIn = false;
        isFadeOut = true;
        yield return new WaitForSeconds(5.0f);
        isFadeOut = false;
    }
}
Game Flow
 
 
Inspiration
Zhou Gong’s Dream Interpretation, also known as “The Interpretation of Dreams”, is an ancient Chinese text that is believed to have been written by Duke of Zhou, a prominent figure in Chinese history, more than 3,000 years ago. The book is a collection of interpretations and explanations of dreams and their meanings, as well as advice on how to interpret dreams and use them for personal growth.
The text is organized into categories based on the types of dreams people might have, such as dreams about animals, water, or travel. Each category includes a list of specific dreams and their associated meanings, as well as advice on how to act on or respond to the dream.
The interpretations in Zhou Gong’s Dream Interpretation are based on traditional Chinese beliefs about the relationship between dreams and the individual’s inner life, as well as the broader cultural and social context in which the dream occurs. It is believed that dreams can provide insight into a person’s subconscious thoughts and emotions, as well as their current life situation and future prospects.
 
Today, Zhou Gong’s Dream Interpretation is still widely studied and used in China, and has even gained popularity in other parts of the world as a tool for understanding dreams and gaining insight into one’s inner life.
 
 
Based on this, I designed the game mechanism:
 
View an abstract and chaotic image of an NPC’s dream and guess its meaning before consulting the dream interpretation manual. NPC will recall scenes from their dreams. Through the illusion mirror, the player can see the scene of the NPC’s dream. The screen is an abstract picture that has been processed by the AI, and the player has to guess what kind of imagery it essentially represents. Finally, consult the dream interpretation manual and submit your results.
 
Code
Name
Code
DreamManager.cs
public class DreamManager : MonoBehaviour
{
    public GameObject FadeIn;
    private bool isFadeIn;
    private bool isFadeOut;
    public GameObject[] DreamImgs;
    public static DreamManager Instance;

    private int index;
    private string PlayerName;

    // Start is called before the first frame update
    void Start()
    {
        index = 0;
    }

    private void Awake()
    {
        if (Instance == null) Instance = this;
    }

    IEnumerator HandleNextdayFade()
    {
        yield return new WaitForSeconds(1f);
        FadeIn.SetActive(true);
        isFadeIn = true;
        isFadeOut = false;
        yield return new WaitForSeconds(2.5f);
        index++;
        isFadeIn = false;
        isFadeOut = true;
        ChangeImg();
        yield return new WaitForSeconds(2.0f);
        isFadeOut = false;
        FadeIn.SetActive(false);
    }

    public GameObject FindDreamImgOnName(string name)
    {
        for(int i = 0;i<DreamImgs.Length;i++)
        {
            if (DreamImgs[i].name == name)
            {
                index = i;
                return DreamImgs[i];
            }
        }
        index = -1;
        return null;
    }

    public void HandleActiveDream(string playerName)
    {
        StartCoroutine(HandleNextdayFade());
        PlayerName = playerName;
    }

    void Update()
    {
        if(isFadeIn)
        {
            Color c = FadeIn.GetComponent<Image>().color;
            c.a += Time.deltaTime / 2;
            FadeIn.GetComponent<Image>().color = c;
        }
        else if(isFadeOut)
        {
            Color c = FadeIn.GetComponent<Image>().color;
            c.a -= Time.deltaTime / 2;
            FadeIn.GetComponent<Image>().color = c;
        }   
    }
}
 
After simple research, writing a dialog system from scratch is not practical (even for professional programmers it would take months). Therefore, I used the dialogue system for Unity plugin to help me implement the dialogue function faster.
 
Appaisal for Dialogue System for Unity (DSU)
 
In fact, the software is far more complicated to use than I expected. It does reduce the amount of programming used, but it doesn’t mean it’s easier.
 
Moreover, none of Unity’s built-in UI components interact with each other due to my introduction of the plugin. After a period of debugging, I found that DSU was occupying Unity’s Event System.
 
Then I spent a whole day reworking the whole scene, which in hindsight was stupid !! Fortunately, in the end, I was able to solve the problem smoothly, even if it made the whole scene hierarchy very complicated.
 
Dialogue Example

Character Design

Tao is a 25-year-old oriental psychic journeying west in search of truth. He offers players a unique, detached perspective, standing as an unaffected outsider in the game’s unfolding conflict. His neutral stance allows for objective observation and understanding of the war.
Tao
Mila represents the perspective of the child in the game. Children can not understand war, or even the meaning of death. Just like in the movie “La vita è bella,” where the son’s perception of life in the concentration camp is portrayed as a game by his father, a child’s understanding of things is based on their education.
Mila
Radoslav represents the perspective of young people before the start of World War I in the game. They are influenced by propaganda and generally believe that war is a good opportunity to achieve success and social mobility. Nationalistic ideas may also be reflected in his character.
Radoslav

Aesthetics

– Props & UI

Documentation

full-text
digital sketchbook

Documented the entire research and development process of this project.