Week 13 – Wrapping up garden scene and voice overs

MAY 20 → MAY 23 – 2024

Tasks

Technical Developments

  • Replaced old voice overs
    • As our client provided us with new voice overs so I cut them up and re-imported them into the project. As the setup remained the same I only had to replace the placeholder versions with the new files.
  • Added a script to control character frames
    • It was not feasible to expect fully rigged and 3D modelled characters due to sudden time constraints so we had to find a different way. I wrote a script that can be easily edited in the Unity editor to set what pose to use for how long.
      (see code & example below)
  • Wrapped up the second scene
    • After advancing the development of the paper interaction I brough everything together and finalised scene two as well. This included the interactions, voice overs and character placeholders.
  • Simulated scene one and four interaction
    • As I finished scene two I decided to soft implement scene one and four as well. There were no assets for these scenes yet but I implemented the needed GameSceneData script and laid out the foundations.

Miscellaneous

  • Communicational issues with our client
    • During the week we were notified by the team lead that our client was not happy with the progress and that we should have had weekly meetings so he could stay on top of it. This was apparently e-mailed to our teachers directly, surpassing us.
    • We then discussed as a team and were very suprised by this whole ordeal but decided to meet every Monday morning at 11:00 from now on.
    • I listened to the new voice overs and had some pointers that I would like to discuss with our client. He did not really help either, I was asking for the Dutch voice overs too as he had placeholders so I could at least implement them. But they were never sent.

Double Diamond

The most difficult part this week was coming up with a good solution for our problem regarding not being able to model and rig the characters.

Discover

I researched methods to achieve what I wanted but did not really find any proper sources that could be implemented. So instead I set out to create my own solution.

Define

The solution would be to create a custom script. Something that could hold multiple images as ‘poses’ and could have a set time before the next image would be used.

The only downside to this solution would be that it takes quite some time.

Develop

I wrote a custom script that holds a list of a custom CharacterPose class, which in itself holds a list of CharacterSubPoses. In this subpose, I could then easily set a name, time to next image and texture to use. These were then used as a coroutine repeatedly, so after the set time expired, there would be a new image used on the character. Creating an effect similar to animation.
(see code below)

Deliver

The progress for this week was not shown to our client, as it had become clear he did not understand the process and could not manage his expectations which impacted us negatively. Therefore, I decided to keep it under wraps for now until we were 100% sure that this was the solution that we would go with.

I did create another release on Github that showcased the full forest scene, it was now finalised and there would be no further additions.

Plan

Next week we’ll start off by having a weekly stand-up meeting with our client. After that I will start implementing SFX and try to improve some of my older scripts until I can implement new art.


Research

The research done this week was not through YouTube but instead through conversation with people around me. I picked some brains to see how they would go about ‘animating’ a character in the way we need. After taking in their opinions and notes I came up with my own solution.


Reflection

The week started off rough with the e-mail that was sent to our teachers. We did not expect that and it was not fair to us. This all left the team in a bit of a somber and unmotivated state. I am happy I still got things done but I too, did not feel too good. This was another breach of trust in my opinion and it was not the first time that there had been issues with him.

Other than that, the work I delivered was solid and I am happy with the solution I had come up with.

Media & code

My solution for our animation problem.
The garden scene, complete with interaction and the grandma changing frames.
    public void SetPose(string pose)1
    {
        textures.Clear();

        for (int i = 0; i < poses.Count; i++)
        {
            if(poses[i].name == pose)
            if (poses[i].name == pose)
            {
                material.mainTexture = poses[i].texture;
                foreach (CharacterSubPose subPose in poses[i].subPoses)
                {
                    textures.Add(subPose.texture, subPose.delayToNextPose);
                }

                if (changeTextureCoroutine != null)
                {
                    CoroutineHandler.Instance.StopCoroutine(changeTextureCoroutine);
                }

                changeTextureCoroutine = CoroutineHandler.Instance.StartCoroutine(ChangeTextureOverTime());
            }
        }
    }

    private IEnumerator ChangeTextureOverTime()2
    {
        foreach (var kvp in textures)
        {
            material.mainTexture = kvp.Key;
            yield return new WaitForSeconds(kvp.Value);
        }
    }
}

[Serializable]
public class CharacterPose3
{
    public string name;
    public List<CharacterSubPose> subPoses;
    [TextArea(3, 10)]
    public string description;
}

[Serializable]
public class CharacterSubPose
{
    public string name;
    public float delayToNextPose;
    public Texture texture;
    [TextArea(3, 10)]
    public string description;
}
  1. The method that can be called from the GameSceneData scripts by passing in the name of the desired pose. ↩︎
  2. The coroutine that is responsible for changing the frame after x time. ↩︎
  3. The pose, which is shown in-editor in the first image. This holds all necessary data and can be accessed and edited within the editor. ↩︎

Week 11 – Figuring out flying paper and new scene

MAY 6 → MAY 9 – 2024

Tasks

Technical Developments

  • Implementing paper collection hint
    • As we found that Rive (an application for vector animations that Yonah & Joris were using) did not work in our Unity project, we had to come up with a different solution.
    • I decided to write a script that would go through sprites and replace the image with the corresponding sprite.
      (see code below)
  • Working on paper physics
    • As the interactions for scene three were finished, we decided to get started on the next-most interactions heavy one. This would be the garden, as there was an interaction with paper flying around.
    • I researched paper physics and tried to find resources online of people who had previously tackled this issue.

Miscellaneous

  • Ascension day

Double Diamond

My main objective this week was tackling the issue that falling paper would be. The physics are really hard to replicate in a simple manner as it would also have to be performant enough for Android.

Discover

I conducted research into paper physics and tried to find resources of people that had previously done work like this. I also researched what would be the best way to create the effect.

Define

Eventually I decided on just animating gameobjects through script, some sort of visual effect would have been possible too but based on the particle systems in scene three I decided against it with perfomance in mind.

The goal would be to write a script that can be activated from a ‘Controller’ after which the paper flies up and floats down similarly to an actual piece of paper.

Develop

Knowing my goal I got to work and quickly stumbled upon a resource on GitHub (listed below) that was called FeatherFall. Which was a script for Unity that closely replicated a piece of paper or other light object falling down.

After importing and tweaking this script a bit I also wrote my own Paper script, that would inherit from Interactable and would be called by my InputManager when interacted with. This followed the same structure as previously used in scene three for the trash. Next to that I wrote a controller script that could simultaneously call all paper sheets.

Deliver

The progress for this week was recorded in a video. Which was also sent to our client, after which he provided feedback about the paper not being allowed to the touch the ground as it was holy. I then explained to him what the technical ramifications would be and we decided it would be fine in this case.

Plan

The plan for next week is to finish the second scene including paper interaction and physics, implement new voice overs that our client sent us. Also, I will be looking for a way to control emotions for our characters as 3D modelling and rigging them does not seem feasible anymore at this moment in time.


Research

Most of the research I have done this week was aimed towards figuring out how paper functions in terms of physics and how to convert that into Unity. For this I watched the following videos.

Falling Paper VFX for Unity https://www.youtube.com/watch?v=D0rzbu5XHOk

[Unity Asset] Falling Paper VFX https://www.youtube.com/watch?v=GDoSP_5rRBg

I also found a great resource on GitHub and read some forum posts.

How to make a simple object fall as a piece of paper? https://discussions.unity.com/t/how-to-make-simple-object-that-would-fall-as-piece-of-paper/252318

VFX Flying Paper https://assetstore.unity.com/packages/vfx/particles/vfx-flying-paper-95726

unity-feather-fall https://github.com/bjennings76/unity-feather-fall


Reflection

The paper physics were very difficult to pin down but I still feel like I could have had it done faster instead of having to move it to next week. Other than that, I am quite satisfied with my current progress; The second scene is coming along nicely due to the structure I had already set up weeks ago, as well as coming up with a creative solution for the animations that weren’t possible in rive.

Media & code

Paper flying with semi-realistic paper physics.
Swipe animation through code.
public class PaperController : MonoBehaviour1
{
    [SerializeField] private List<PaperSheet> papers;

    public void BlowPapers()
    {
        foreach(PaperSheet paper in papers)
        {
            paper.Blow();
        }
    }
}
public class ImageAnimation : MonoBehaviour
{
    public Sprite[] sprites;
    public int spritePerFrame = 6;
    public bool loop = true;
    public bool destroyOnEnd = false;

    private int index = 0;
    private Image image;
    private int frame = 0;

    private bool isPlaying = false;

    protected void Awake()
    {
        image = GetComponent<Image>();
    }

    protected void OnEnable()
    {
        isPlaying = true;
    }

    protected void OnDisable()
    {
        isPlaying = false;
    }

    protected void Update()
    {
        if (isPlaying)
        {
            if (!loop && index == sprites.Length) return;
            frame++;
            if (frame < spritePerFrame) return;
            image.sprite = sprites[index];
            frame = 0;
            index++;
            if (index >= sprites.Length)
            {
                if (loop) index = 0;
                if (destroyOnEnd) Destroy(gameObject);
            }
        }
    }
}2
  1. Class that holds a reference to all paper sheets to collectively activate them when necessary. ↩︎
  2. Script that holds all sprites from a certain sheet and replaces the image with the next sprite according to the spritePerFrame value. ↩︎

Week 10 – Beautifying the forest and mid-term presentation

APRIL 22 → APRIL 25 – 2024

Tasks

Technical Developments

  • Transitioning forest from dead to alive
    • As the player collects all trash, the forest should react accordingly. For this I added a new script that is used on every tree, this script holds a reference to the dead- and alive tree. Then, when called from the GameSceneData script, the tree will transition within a set time. (see code & gif below)
  • Major issues with referencing prefabs
    • During the week I encountered some issues where objects would not be active even when they clearly were. After hours of debugging I found that I had set up my GameManager all wrong and had been using references to the prefab of the environment instead of the instantiated version at runtime. This led to major issues where I was unable to call any methods and do anything else that had to be done so I had to rewrite a part of the original script but the logic was still solid. (see code below)
  • Added lerping between grass textures
    • After consulting Alejandra we decided on a method to lerp between grass textures when the player has collected all trash. She made the shader and I got to implement it in code.
      (see gif below)
  • Added new interaction to pick a flower seed
    • As our client had previously mentioned that he would like small interactions all over the place, I came up with an idea. As we were using a generic seed for the flower spawning and spawned the same flower every time, I thought it could be cool to have a choice. So I implemented the flowers that Alejandra made and added flower packs from which the player could choose.
      (see gif below)

Miscellaneous

  • Mid term presentation
    • Presented our current progress to our assessing teachers and our client. They provided us with a good amount of feedback which was then applied and processed accordingly.

Double Diamond

This week was an accumulation of small improvements that brought a major improvement to the scene. The goal was to implement several visual improvements and fixes like removing the fire, transitioning the trees and lerping the grass.

Discover

My research this week was not through online sources but instead through consultation with my team members. Moreover, I mainly discussed with Alejandra how to approach certain parts like lerping the grass, but also how to transition the trees and make it look good.

Define

We decided on a simple grass lerp in a shader that Alejandra would make, after which I would implement it in script. Next to that, we decided that simply scaling down one tree and scaling up another would be more than fine.

Develop

I took these definitions to Unity and implemented them as proposed. I also created a separate editor script so it would be easy for Alejandra to implement new trees and toggle between the dead/alive ones. Next to that I implemented the grass lerping by adding a boolean that waited for the trash to be collected.

Deliver

These developments resulted in a few videos that were sent to the client as well as in our teams discord to receive feedback.

Plan

Next week I plan to get started on the next scene and it’s interactions. These include picking up paper, but more importantly I aim to figure out the paper physics during the week as I want to create a semi-realistic behaviour.


Research

As mentioned the research this week was mainly from discussing with Alejandra and learning more from her about shaders in Unity as well as trying my hand at editor scripting again.


Reflection

Another solid week in my opinion. I got quite a number of things done and brough major improvements to our current scene, as well as finalising some parts that had been backlogged for a while.

The collaboration between the artists and myself went really well too and I feel like we are on the same wavelength in terms of communication and expectations.

Media & code

Transition between dead and alive trees.
Flower choice through coloured ‘packs’ and corresponding flower spawns.
The grass lerp in action through the editor.
Playthrough with characters and localized pop ups.
private void HandleTrashCollection()
    {
        int index = (int)Mathf.Floor(trashProgressScript.ReturnCurrentScore() / actionPoint);

        if(index <= particleSystemsBase.Count - 1)
        {
            particleSystemsBase[index].GetComponent<ParticleSystem>().Stop();
        }

        if (index <= particleSystemsExtra.Count - 1)
        {
            particleSystemsExtra[index].GetComponent<ParticleSystem>().Stop();
        }

        if(index <= treeSwitcher.Count - 1)
        {
            treeSwitcher[index].ActivateTransition();
        }
    }1private void HandleTrashCollection()
    {
        int index = (int)Mathf.Floor(trashProgressScript.ReturnCurrentScore() / actionPoint);

        if(index <= particleSystemsBase.Count - 1)
        {
            particleSystemsBase[index].GetComponent<ParticleSystem>().Stop();
        }

        if (index <= particleSystemsExtra.Count - 1)
        {
            particleSystemsExtra[index].GetComponent<ParticleSystem>().Stop();
        }

        if(index <= treeSwitcher.Count - 1)
        {
            treeSwitcher[index].ActivateTransition();
        }
    }
    [SerializeField] private GameObject deadTree;
    [SerializeField] private GameObject liveTree;

    [SerializeField] private float speed = 1.0f;
    [SerializeField] private AnimationCurve blendCurve;

    private Vector3 initialScale;
    public bool transitionActivated = false;
    private float blend = 0;

    protected void Start()
    {
        initialScale = transform.GetChild(0).transform.localScale;
    }

    private void Update()
    {
        if (transitionActivated)
        {
            blend = Mathf.Clamp01(blend + Time.deltaTime * speed);

            float modifiedBlend = blendCurve.Evaluate(blend);

            deadTree.transform.localScale = initialScale * (1 - modifiedBlend);

            liveTree.transform.localScale = initialScale * modifiedBlend;

            if (blend >= 1)
            {
                transitionActivated = false;
            }
        }
    }

    public void ActivateTransition()2
    {
        if (transitionActivated)
        {
            transitionActivated = false;
        }
        else
        {
            transitionActivated = true;
        }
    }
  1. Method to handle the trash collection, turn off the fire and toggle the trees to transition. ↩︎
  2. By calling this method, the blending will start and end when it reaches the full value. ↩︎

Week 9 – Structure and localization

APRIL 15 → APRIL 18 – 2024

Tasks

Technical Developments

  • Scene structure
    • Decided on a structure to use for our project, as the project has boundaries in terms of scale (e.g. five scenes) I decided to use a setup where, based on events, the next method gets called through subscription. (see code and explanation below)
  • Full scene playthrough
    • Finalised the structure of a complete scene, completed with interactions, voice overs and environment art. (see video below)
  • Localization support
    • Installed the Unity Localization package to ensure support for (at least) two languages; Dutch and English. Through the use of a string database I was able to easily add dual language support.

Miscellaneous

  • Mid term presentation preparation
    • Started collecting materials to present at the upcoming mid-term presentation.
  • Procedural art redo deadline
    • Delivered my procedural art project in time.

Double Diamond

Finally a week filled with programming once again, this week revolved around creating a flexible setup for our scenes as well as finishing up a complete playthrough of the third scene. Next to that our client had identified an issue, there was no dual language support yet. So I decided to implement that too.

Discover

My research this time around was based around researching a state-machine. I thought that this would be helpful to control the different scenes and be able to pass on data easily. I also did research into adding multiple language support.

Define

The state-machine was too large for a project like this and so instead I decided to use a subscription system. This would then work through simply subscribing to events and unsubscribing every time. This made the setup easy but possibly more time-costly then using a state-machine. However, having to set up such a machine would be a bigger time sink in total.

Develop

I set up a rigorous approach to the subscription system by using an abstract class that every scene would be based on. Then, the root object would hold this script and also contain the necessary references. After which events for interaction and voice overs were listened to and handled accordingly.
(see code below)

Deliver

These developments resulted in a full playthrough for scene three being available. I sent our client the video below and also created a release on our GitHub.

Plan

My plans for next week include presenting the mid-term presentation, adding a transition from a dead forest to a living one as well as other fixes scene three still needs.


Research

As mentioned the research this week was primarily state-machine based even when I decided against using it in the end. I watched the following videos.
These videos did inspire me to create my own, more specific and smaller setup.

Game Manager – Controlling the flow of your game https://www.youtube.com/watch?v=4I0vonyqMi8&t=497s

How to use Bolt State Machines in Unity https://www.youtube.com/watch?v=SVpkh3kMIcg

Unity 2D Scene Management Tutorial https://www.youtube.com/watch?v=E25JWfeCFPA

Programming a Better State Machine https://www.youtube.com/watch?v=qsIiFsddGV4

Build a better finite state machine in Unity https://www.youtube.com/watch?v=NnH6ZK5jt7o

The State Pattern (C# and Unity) – Finite State Machine https://www.youtube.com/watch?v=nnrOhb5UdRc&t=260s


Reflection

I was really happy with my progress this week as well as finally having a week without major distractions. The code I have written this week was really good and I am sure that it provides a stable foundation for the next scenes.

The part I am most happy with is that I came up with the solution myself, I found that it would be easier to do something small like this even when it takes more time and this also enabled me to really customize it to the experience we want to provide. I had not really used abstract classes before but I saw it in one of the researched tutorials and immediately knew I had to use it.

Media & code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public abstract1 class GameSceneData : MonoBehaviour
{
    public abstract void OnSceneEnter();2
    public abstract void OnSceneExit();
}
public class GameSceneAdditionalObject3
{
    public int sceneIndex;
    public int inSceneIndex;
    public GameObject additionalObject;
    public Transform parent;
}
if(scene.sceneEnvironmentPrefab.GetComponent<GameSceneData>() != null)4
                {
                    scene.sceneEnvironmentPrefab.GetComponent<GameSceneData>().OnSceneEnter();
                }
public override void OnSceneEnter()5
    {
        additionalObjects = GameManager.Instance.GetAddditionalObjects();
        audioManager = AudioManager.Instance;

        trashProgress = additionalObjects[0].additionalObject;
        swipeArea = additionalObjects[1].additionalObject;
        seedSpawnpoint = additionalObjects[2].additionalObject;
        popUp = additionalObjects[3].additionalObject;

        audioManager.PlayVoiceOver("ForestScenePart1");
        audioManager.OnVoiceOverFinished += StartTrashPicking;
    }


private void StartTrashPicking()
{
    // First we de-activate the old objects

    // Then we unsubscribe from previous events
    audioManager.OnVoiceOverFinished -= StartTrashPicking;

    // Then we activate new objects and call the needed methods
    trashProgress.SetActive(true);

    // Then we subscribe to new events
    trashProgressScript.OnScoreReached += StartSeedVoiceOver;
}
  1. This class is marked as abstract to be able to override it later for every scene. ↩︎
  2. The class holds two ‘default’ methods. Meaning any script that inherits from this class has to implement those methods. ↩︎
  3. Additionally, this class holds references to objects already in the scene (usually UI). This is done as the instantiated prefab can not otherwise have references to these objects without large costs. ↩︎
  4. This if statement is found in the GameManager script, whenever a new scene is scanned, the script checks to see if it has a script that inherits from GameSceneData (the first script) and if it does it calls the OnSceneEnter method. ↩︎
  5. This is an example of an implemented version of the GameSceneData script, when entering the scene all additional objects are referenced and stored, the first voice over is activated as well as subscribing to an event for when the voice over ends. After it ends, the next method will be called etc. ↩︎
A lite playthrough of our first finished scene.

Week 8 – Amsterdam trip and trash picking

APRIL 8 → APRIL 11 – 2024

Tasks

Amsterdam Trip

  • We met up with Abner at the trainstation of Amsterdam Amstel after which we had a busy day, filled with meetings with employees from various museums as well as the museum our installation will be placed in.
  • Learned more about consumer engagement in museums by observing the inner workings at Tellarts, Micropia and JCK.

Technical Developments

  • Managing version control
    • Taught another team member the proper way of working with Git through Pull Requests, Code Reviews and Merging.
  • Assisted on a UI issue
  • Rewrote script to keep track of the amount of trash collected in the scene three interaction

Miscellaneous

  • Mid term peer review (see image below)
    • Filled in the peer review spreadsheet to identify areas of improvement.
  • Procedural Art redo

Double Diamond

The majority of this week was spent outside of development but I still managed to do some work. Most of this was to do with the rewriting of a previously made script for trash collecting, more specifically the score tracking for it.

Discover

I came up with a more flexible solution that would lower the number of lines in the script as well as providing a more efficient solution in general. (see code below)

Define

The trash progress script showed a pop up with specific type and scoring for every object that was picked up. We decided that that was not necessary and so I rewrote the script to set it up more scalable and future proof.

Develop

I threw out the previous code that went through a Dictionary of trash types with their respective scores and instead simply added the score to the current score. This should see some more improvements later.

Deliver

As the development made this week was not visually different there was no specific deliverable.

Plan

Next week I will focus on finishing up scene three as far as possible to create a sort of vertical slice. I will also research how to set up the various scene in terms of functionality.


Research

This week my research was mainly conducted in person with several employees from aforementioned museums. Next to that we observed and learned from the existing interactions in these museums.


Reflection

This week was a hectic one, from Amsterdam to Enschede and finally Veenendaal. I moved around a lot and was also distracted by my redo for Procedural Art. Looking back at it, I could have done more this week but in the end I am not unhappy with the results I achieved and moreso the experience gained from the trip to Amsterdam.

We learned quite a lot and got to experience really cool installations too, which is always very valuable.

Looking at the peer review my main areas of improvement would be arriving on time and being more vocal about providing feedback and motivating my fellow team members.

Media & code

public void SetTotalScore(int score)
    {
        List<Trash.TrashType> trashTypes = new List<Trash.TrashType>();

        foreach(TrashItem trashItem in trashItems)
        {
            if (trashTypePair.ContainsKey(trashItem.trash.trashType))
            {
                trashTypePair[trashItem.trash.trashType] += 1;
            }
            else
            {
                trashTypePair.Add(trashItem.trash.trashType, 1);
            }

            if (!trashTypes.Contains(trashItem.trash.trashType))
            {
                trashTypes.Add(trashItem.trash.trashType);

                GameObject item = Instantiate(itemPrefab, itemParent);

                ItemData itemData = item.GetComponent<ItemData>();
                itemData.icon.sprite = trashItem.icon;
                itemData.scoreText.text = trashTypePair[trashItem.trash.trashType].ToString();
            }

            totalScore += trashItem.trash.Score;
        }

        Debug.Log(totalScore);
        totalScore += score;

        RefreshUI();
    }
Our filled in peer reviews.

Week 7 – Flower power and meeting with client

APRIL 1 → APRIL 4 – 2024

Tasks

Client Meeting

  • Met with the client to discuss details of an upcoming trip to Amsterdam to meet his client(s).

Technical Developments

  • Finished implementing a seed throw mechanic
    • Finalised calculations for the seed throwing.
    • Succesfully detected swipes and swipe speed.
  • Implemented a flower spawn based on previous mechanic

Double Diamond

The majority of this week was spent on further advancing the seed throwing mechanic as well as adding a flower that spawns where the seed collides with the ground.

Discover

To be able to finalise the seed throwing I did some more research into the pokemon throw to combine my current knowledge and see if a final solution can be found.

Define

The objective remained the same as last week, implementing a pokemon like throw to allow the player to swipe a certain direction at a certain speed and achieve coherent results.

Develop

I started with two new tutorials, these provided new insights and led me to a more final solution. The biggest part was tweaking the variables until it felt responsive and intuitive to use. (see code below) After that, the only thing left for this week was implementing a flower spawn.

Deliver

Nearing the end of the week I managed to finish the seed throwing and also implement the flower spawning. Both of these were then recorded and sent to the client in video format. He was positive about the development. I also made another release on GitHub to go with the development.

Plan

Next week will start with a trip to Amsterdam, where we will meet the Museum’s representatives as well as going to a few other museums for inspiration. The rest of the week’s focus will primarily be on Procedural Art for me personally.


Research

After an unsuccesful week last week, I decided to do one final dive into the pokemon ball throwing and stumbled upon these two tutorials. They gave me the last insight needed to finish the mechanic.

How to Add Force to Gameobject with Swipe to Throw It In 3D Android Unity Game? SImple Tutorial https://www.youtube.com/watch?v=7O9bAFyGvH8&t=1s

Pokemon Go Throwing Mechanic in Unity https://www.youtube.com/watch?v=eKhmcPa_Fjg&t=5s


Reflection

This week was, in contrary to the previous one, a really succesfull week. I managed to finish the throwing mechanic, as well as implementing the flower spawning. This means that all interactions are done for scene three, which in turn means that based on the art the scene can be finished soon.

Next to that we had a good meeting with our client regarding next week’s trip to Amsterdam and he was positive about my work this week.

Media & code

Showcasing seed collision in AR.
Showcasing the seed throwing mechanic and flower spawn.
Vector2 xyForceDirection = new Vector2(-direction.x, -direction.y);

                    Vector3 force = new Vector3(xyForceDirection.x * throwForceX, xyForceDirection.y * throwForceY, 0) +
                                Camera.main.transform.forward * (timeInterval * throwForceZ);

                    // Add force to objects rigidbody in 3D space depending on swipe time, direction and throw forces
                    rb.isKinematic = false;
                    rb.AddForce(-direction.x * throwForceXY, -direction.y * throwForceXY, throwForceZ / timeInterval);
                    rb.AddRelativeForce(force);1
  1. By removing the previous line and instead making the force relative, I achieved way better results. ↩︎

Week 6 – Physics are hard

MARCH 25 → MARCH 28 – 2024

Tasks

Technical Developments

  • Tried to implement a Pokémon like throw for the seeds
    • Struggled with using physics to create a trajectory for the seed.
    • Detecting swiping proved to be more difficult than expected.

Miscellaneous

  • Attended one Applied Research class
  • Procedural Art redo

Double Diamond

The whole week was spent on researching and developing a pokemon like throw to allow the player to throw and plant seeds. This proved to be more difficult than expected at first as I had never worked with physics like this before.

Discover

To discover what method to use and how to implement the throw, I conducted some research into the topic and found interesting tutorials. I also looked at Pokémon Go to see what they used there, as it was one of my main inspirations. (Research can be found below)

Define

The objective is to create a modular solution that detects a players swipe input and throws the seed accordingly. This is dependent on a few factors that are difficult to implement, mainly converting the 2D swipe to a 3D movement.

Develop

I started with following a tutorial that covered basic swipe detection, this was not very intuitive and so it took me longer than expected. After finalising the swipe detection for now I dove deeper into the throwable object and how to calculate it’s trajectory.

Deliver

The progress I had at the end of the week was not in a presentable state and honestly, still was not good enough or even close to my set target. However we did make a release on Github, where the art was combined with the latest stable version of the technical side.

Plan

Next week will revolve around finishing the seed throwing as well as implementing flower spawning. We will also have a meeting with our client to discuss details for an upcoming trip to Amsterdam (where our client’s client is based).


Research

As most of the week was spent on developing a solution for the seed throwing, that was also my main point of research this week.

Next to that I did some research into general detection of swipes in Unity, which I was also quite unfamiliar with.

Recreating Pokemon Go in Unity3D #9 Pokemon catching 1/2! https://www.youtube.com/watch?v=a4ts4dZ_12I

Recreating Pokemon Go’s camera in Unity3D #4 Pokeball throwing! https://www.youtube.com/watch?v=wavvtztVK3c

Unity3D Recreating Pokemon Go : Part 1 / The Basics https://www.youtube.com/watch?v=XH942mANiv4

Pokemon Go Throwing Mechanic in Unity https://www.youtube.com/watch?v=eKhmcPa_Fjg&t=5s

Unity Swipe Controls – Easy Tutorial https://www.youtube.com/watch?v=Pca9LMd8WsM


Reflection

At the end I am not too happy with the overall progress I made this week. It proved to be more than I could do, in hindsight I could have known as both physics and swipe detection are topics I am entirely unfamiliar with.

Hopefully I can manage to finish this early next week so that I can catch up on my other tasks.

Media & code

// Add force to objects rigidbody in 3D space depending on swipe time, direction and throw forces
                    rb.isKinematic = false;
                    rb.AddForce(-direction.x * throwForceXY, -direction.y * throwForceXY, throwForceZ / timeInterval);

Week 5 – Refactoring and other responsibilities

MARCH 18 → MARCH 21 – 2024

Tasks

Meetings

  • Meeting with Hester van der Ent
    • Catching up on our progress.
    • Discussing a previously brough up issue regarding copyright.
  • Meeting with Harry Sanderink
    • Catching up on our progress regarding our learning outcomes.

Technical Developments

  • Refactoring our codebase
    • Introduced a GameManager working with the GameScene created last week, this also included an active/inactive state to control whether or not to show the scene’s environment. (see code below)
    • Reviewing my previously written scripts to see if there is any space for improvements.
  • Managing version control
    • Merged two new branches made by Alejandra.
  • Designing a scalable system to allow multiple people to play simultaneously (see video below)
    • Person 1 can start at pillar A and continue in sequence ABCDE, while person 2 can start at C and continue in sequence CDEAB.
    • Allowing multiple people to play at the same time by customizing their starting pillar.

Miscellaneous

  • Attended the Reality Check Festival
  • Attended two Applied Research classes
  • Decided on a weekly stand-up with the team

Double Diamond

Most of this week was spent on improving existing scripts as well as removing unnecessary ones to replace them with a more flexible solution.

Define

The main issue that persisted from last week was the fact that it was really difficult to create content without it taking a long time. This could be prevented by offering a modular solution (like Scriptable Objects) to do most of the work and having it pass through the needed methods when necessary.

Develop

I continued where I left off last week and added another improvement to the GameScene script. From now on, the GameManager has the ability to see if a scene is already active, if it is, there is no need to go through the rest of the processing. This saves performance and makes it easier to track what scene is being played out.

Deliver

This prototype was not released anywhere as it has become clear that our client needs clear visuals to explain what is happening and I did not find that feasible for a technical solution like this.

Plan

For next week, my most important point is to finish the refactoring. After that I will start to work on the next interaction for our chosen scene: throwing flower seeds. I have never before worked with physics in Unity so I expect this to take more time than the previous interaction.


Research

After a suggestion from Alejandra, I did some research into rebasing for Git. Currently we are using a classic Pull Request > Review > Merge construction. However, it was suggested that rebasing can be used too. Ultimately we decided against it but it was interesting to note the various ways of achieving a solid grip on version control.

Rebasing and pull requests in comparison.

Reflection

While the refactoring takes a little longer than I had hoped, I am still satisfied with my current progress. Especially considering this week was full of distractions with Reality Check and Applied Research.

I did begin to see some possible issues with the client, as communication is not always smooth and there have been some instances where I felt we weren’t really listened too.

Media & code

public void StartGame()
    {
        SetPlayerIndex(playerIndexDropdown.value);

        Destroy(mainMenuUI);

        SetSpawnablePrefabs();

        imageTracking.SetSpawnablePrefabs();
    }

    public void SetActiveScene(GameObject scenePrefab)
    {
        foreach(GameScene scene in modifiableScenes)
        {
            SceneState.State state = scene.sceneState.state;

            if (scenePrefab.name == scene.sceneEnvironmentPrefab.name)
            {
                if(scene.sceneState.state == SceneState.State.Active)
                {
                    break;
                }

                scene.sceneState.state = SceneState.State.Active;

                Debug.Log(scene.sceneName + scene.sceneIndex + " state was changed from " + state + " to " + scene.sceneState.state);
            }
            else
            {
                if(scene.sceneState.state is SceneState.State.Active)
                {
                    scene.sceneState.state = SceneState.State.Inactive;

                    Debug.Log(scene.sceneName + scene.sceneIndex + " state was changed from " + state + " to " + scene.sceneState.state);
                }
            }
        }
    }1public void StartGame()
    {
        SetPlayerIndex(playerIndexDropdown.value);

        Destroy(mainMenuUI);

        SetSpawnablePrefabs();

        imageTracking.SetSpawnablePrefabs();
    }

    public void SetActiveScene(GameObject scenePrefab)
    {
        foreach(GameScene scene in modifiableScenes)
        {
            SceneState.State state = scene.sceneState.state;

            if (scenePrefab.name == scene.sceneEnvironmentPrefab.name)
            {
                if(scene.sceneState.state == SceneState.State.Active)
                {
                    break;
                }

                scene.sceneState.state = SceneState.State.Active;

                Debug.Log(scene.sceneName + scene.sceneIndex + " state was changed from " + state + " to " + scene.sceneState.state);
            }
            else
            {
                if(scene.sceneState.state is SceneState.State.Active)
                {
                    scene.sceneState.state = SceneState.State.Inactive;

                    Debug.Log(scene.sceneName + scene.sceneIndex + " state was changed from " + state + " to " + scene.sceneState.state);
                }
            }
        }
    }
  1. GameManager script ↩︎

Week 4 – Interaction and refactoring for scalability

MARCH 11 → MARCH 14 – 2024

Tasks

Technical Developments

  • Setting up interaction (see video below)
    • We decided to start with scene three as it was most interaction heavy so we wanted to get that out of the way while also having our setup fit a scene like this.
    • Added a ‘Trash’ class that is tagged as an Interactable and can be clicked. After which the InputManager handles the further proceedings.
    • Added a custom score per ‘Trash’ object. This is to ensure it can be used for the actual implementation later on.
    • Implemented dummy objects from a Synty asset pack to function as trash until an artist makes the actual models.
  • Starting refactoring process
    • Began with the foundation, creating a Scriptable Object pipeline.
      • The first scriptable object, GameScene, holds all necessary data per scene. Such as name, index, referenced object and a method for cloning. (code below)
      • Figured out I had to clone the scenes as to not change them permanently from code. As they are Scriptable Objects.

Miscellaneous

  • Driving exam (I passed yay)

Double Diamond

During this week I mainly focused on the interaction and started researching and planning the refactoring towards the end of the week.

Discover

Researched good solutions for my scalability problem while still being able to develop for Android and keeping the project clean and transparent.

Define

After gathering all the facts I decided to work with a Scriptable Object solution that would hold all data per scene. This would then be read by the needed scripts (mainly the GameManager) to process its data and work with the scenes as intended. This ensures scalability and ease of use as Scriptable Objects work wonders for setting up a small project like this.

Develop

Created the first working prototype that does as described above, the models are placed according to the images detected. This also works in real life but we don’t have access to a phone capable of AR at this moment in time.

Finished a simple prototype that includes interaction at the beginning of the week and later merged it with Emma’s (artist) work, to have it be more of a forest environment. This prototype implemented an InputManager handling the clicking of Interactable objects by accessing their scripts to call the needed method.

Deliver

This prototype was not posted as a release on Github but was instead sent to our client in video format. After which he provided feedback.

Plan

Next week’s plan is to further lay out the foundation of a scalable and performant framework. Based on Scriptable Objects and script inheritation. This should hopefully not take more than a week and in return, provide me with a solid base on which I can then more easily add features and improvements.

There will also be a Reality Check Festival, which is a festival hosted by our studies which we will all attend.


Research

The research conducted this week mainly revolved around trying to find a good solution for our scalability issues. Everything I found pointed towards using Scriptable Objects and while I do have experience with those already, I still decided to do some more digging into the subject.


Reflection

This fourth week started really well, I managed to implement the interaction quite quickly and it immediately was in a solid state.

Unfortunately I also learned the repercussions of not setting up the project in a scalable manner and found that I now had to work on refactoring and starting (almost) from scratch again to allow the project to remain possible in a clean manner. This was a major learning point for me and in hindsight, I am glad that it happened here.

Media & code

First iteration of the interaction system working.
Combining Emma’s work with my interaction.
[Serializable]
[CreateAssetMenu(fileName = "New Scene", menuName = "Eden/Scene", order = 1)]
public class GameScene : ScriptableObject
{
    public string sceneName;
    public int sceneIndex;

    public GameObject sceneUIPrefab;
    public GameObject sceneEnvironmentPrefab;
    public SceneState sceneState;

    public List<GameSceneAdditionalObject> additionalObjects;

    public GameScene Clone()
    {
        GameScene clone = ScriptableObject.CreateInstance<GameScene>();
        clone.name = sceneName;
        clone.sceneName = this.sceneName;
        clone.sceneIndex = this.sceneIndex;
        clone.sceneUIPrefab = this.sceneUIPrefab;
        clone.sceneEnvironmentPrefab = this.sceneEnvironmentPrefab;
        clone.sceneState = new SceneState { state = this.sceneState.state };
        clone.additionalObjects = this.additionalObjects;
        return clone;
    }
}

[Serializable]
public class SceneState
{
    public State state;

    public enum State
    {
        Active,
        Inactive,
        Hidden
    }
}