Advertisement Jump to content
  • Advertisement
  • entries
    5
  • comments
    4
  • views
    425

About this blog

Dev logs for the war city runner game

Entries in this blog

 

Dev Log #4

Intro This has been some time coming but I guess that is to be expected there wasent enough new content to merit an entire blog post till now since so far the focus has only been polishing whats already there and to be fair I have been losing a little motivation for writing blog posts at the same time I feel like having a record of my work like this is important and in all fairness is pretty cool too look back on so I will continue doing this. That said there has been a major update which is the jump animation. During the course of my integrating the jump animation I realized unity has something called Blend tree for its animation ....I had no idea something like this even existed so I ended up learning something new after all.   StartUp The way my framework well works is that it changes to the state the game currently needs to be in essentially prepares the state getting everything that needs to be ready for that state and removing the things not needed for that state so I needed some way to start the first State as soon as the mainscene loads so I ended up with the StartUp class. The responsibility of this class is to change the state to the required default state as soon as the scene loads or more broadly handle startup operations. public class StartUp : MonoBehaviour { [SerializeField] SceneLoader sceneLoader; // Use this for initialization void Start () { sceneLoader.OnSceneLoadDone += HandleSceneLoaded; } private void HandleSceneLoaded() { StartCoroutine(WaitAndSetState()); sceneLoader.OnSceneLoadDone -= HandleSceneLoaded; } IEnumerator WaitAndSetState() { yield return new WaitForSeconds(0.1f); TreaderFSM.Instance.ChangeState(States.MAIN_MENU_STATE); } }   Loading So initially I wanted to have a loading bar but after some debugging I find that the loading takes 1.6 seconds max and from a user perspective it takes even less. The problem I faced was how do I visually verify if my loading screen is loading correctly if the entire thing takes less time than I take to blink. So I decided to simplify my loading  screen significantly from my initial design atleast till a time where my main scene is large enough to take more time to load. And its not like I am downloading anything.  UILoading This component attached the loading UI is responsible for telling the scene loader to load the scene. public class UILoading : MonoBehaviour { [SerializeField] SceneLoader sceneLoader; // Use this for initialization void Start () { sceneLoader.LoadMainScene(); } }   Config Just as I did in my last game I decided to use scriptable objects to maintain my configurable data currently only for player and obstacles. Player Config Currently maintains jump force and  gravity modifier values. public class PlayerConfig : ScriptableObject { public float jumpForce = 20; public float gravityModifier = 0.5f; } Obstacle Config Currently maintain the initial speed and initial position. public class ObstacleConfig : ScriptableObject { public float horizontalSpeed = 6; public Vector3 initialPosition; }   Player Jump Finally to the main update for this current sprint the jump animation just like last time this is more show than tell kind of situation. Just to be clear I did not create the animations I only did the integration the animations are part of the package from the asset store.  void DoJump() { playerData.mainAnimator.SetBool(PlayerAnimatorKeys.GROUNDED, false); playerData.mainAnimator.SetFloat(PlayerAnimatorKeys.JUMPSPEED, currentForce); currentForce -= playerData.playerConfig.gravityModifier; jumpVector.y = (transform.position.y + (currentForce * Time.fixedDeltaTime)); transform.position = jumpVector; }   Upcoming Next on my list is: 1. Pushing the character when they encounter an obstacle. 2. Build and integrate the end screen UI to tie the whole thing in a neat bow even if incomplete 3. Finally finish my second sprint.

Treader

Treader

 

Dev Log #3

Intro Writing this one at an odd time middle of the week rather than on a Saturday like I had originally planned but better to do something late than never do it at all ...well not always I figure you could find exceptions but this is int one of those. By the time of writing this post I have finally finished the first sprint of the project and plan out the second sprint the second sprint seems to be just a little smaller than the first one but not by much initially I was conflicted on whether or not to dedicate the second sprint only for polishing since that seems to be the majority of what it is right now however given its the second sprint I feel its important to finish the end case of the game which is mostly UI. Main Character So when I started my search for art and animation assets for the character I was really hoping to find one with legs and I did find a few but those tended to be sprites with a weapon held in their arms or too medieval for the game I am making. Eventually I found one with had an urban look with rigged 2D animation that could work I dint really like the look a lot but it was the only one suitable which had legs. That said there was one I fell in love with that dint have legs ...a cool looking furball character I kept debating with myself for a while which went along the lines of 'This character dosent have any legs if I use it can I still call it a runner?' then I eventually figured if we can call an electronic appliance running just because its functioning and not even moving e.g "Is your fridge running?" a furball that's moving can definitely count as running. Player Data This class maintains references for not primitive data relevant to the player my plan is to have different classes for different actions so having a single class maintain references might reduce the overall number of references that need to be maintained.  public class PlayerData : MonoBehaviour { public Animator mainAnimator; public Animator cloudAnimator; public LayerMask groundLayerMask; }   Player Animator Keys This class just maintains a const for animator conditions. public class PlayerAnimatorKeys { public const string SPEED = "Speed"; }   Player Jump So far I have only added the jump functionality for the player. Initially I wanted to use rigidbody2D for the jump and other motion but even when I set ground and player bounce to 0 in the physics material I still noticed an unwanted bounce and the animation was also affecting the rigidbody velocity in an unwanted way so I decided to go ahead and make a custom jump script. public class PlayerJump : MonoBehaviour { [SerializeField] PlayerData playerData; [SerializeField] float jumpForce = 20; //TODO: Needs to come from config [SerializeField] float gravityModifier = 0.5f; //TODO: This needs to come from config bool canJump = true; Vector3 jumpVector; Vector3 fallVector; float ground = 0; float currentForce; private void Start() { ground = transform.position.y; } void InitJump() { jumpVector = transform.position; currentForce = jumpForce; canJump = false; } void DoJump() { currentForce -= gravityModifier; jumpVector.y = (transform.position.y + (currentForce * Time.fixedDeltaTime)); transform.position = jumpVector; } private void OnTriggerEnter2D(Collider2D collision) { if (((1 << collision.gameObject.layer) & playerData.groundLayerMask) != 0) { canJump = true; } } private void Update() { if (Input.GetButtonDown("Jump") && canJump) { InitJump(); } } private void FixedUpdate() { if (!canJump) { DoJump(); } } }   Obstacles Currently I have only a single type of obstacle that is nothing but a white square colored and stretched out into a rectangle. For the obstacle I have decided to go with object pooling since here will be a lot  of them and destroying and initializing seems excessive. Obstacle This is the class attached to all obstacles now that I think of it I might need to make this more specific since there will be a lot more kinds of obstacles in the future and the name might be too vague. Currently all it does is move the obstacle in a single direction. One thing I learned making this game is making the obstacles move in a infinite runner game to give an impressions of the world moving is much easier than making the world move. public class Obstacle : MonoBehaviour { public Action<Obstacle> OnReachedEnd; [SerializeField] float horizontalSpeed = 6; //TODO: This needs to come from config [SerializeField] Vector3 initialPosition; //TODO: this needs to come from congif [SerializeField] GameObject endPoint; Vector3 moveVector; private void Start() { moveVector = initialPosition; } void Move() { moveVector.x = moveVector.x - (horizontalSpeed * Time.fixedDeltaTime); transform.position = moveVector; } private void FixedUpdate() { Move(); } private void OnTriggerEnter2D(Collider2D collider) { if(collider.gameObject == endPoint) { moveVector = initialPosition; if (OnReachedEnd != null) { OnReachedEnd(this); } } } }   Obstacle Populator This is the class responsible for pooling the obstacles and initializing them from prefab. Current idea is as soon as the  first obstacle reaches the end we have enough obstacles and to stop creating more and begin pooling instead. public class ObstaclePopulator : MonoBehaviour { [SerializeField] Obstacle obstacleTemplate; [SerializeField] float timeInterval; //TODO: This should come from config List<Obstacle> obstaclePool; bool stopPopulaing = false; // Use this for initialization void Start () { obstaclePool = new List<Obstacle>(); StartCoroutine(PopulateAtInterval()); } void InitializeObstacle() { Obstacle obstacle; if (obstaclePool.Count == 0) { obstacle = GameObject.Instantiate<Obstacle>(obstacleTemplate, transform); } else { obstacle = obstaclePool[0]; } obstacle.gameObject.SetActive(true); obstacle.OnReachedEnd = HandleObstacleReachedEnd; if (obstaclePool.Contains(obstacle)) { obstaclePool.Remove(obstacle); } } void HandleObstacleReachedEnd(Obstacle obstacle) { obstaclePool.Add(obstacle); obstacle.gameObject.SetActive(false); obstacle.OnReachedEnd = null; } IEnumerator PopulateAtInterval() { while (true) { yield return new WaitForSeconds(timeInterval); InitializeObstacle(); } } }   Main Character and Obstacles  Not much to say here so I leave you with a video of how the gameplay looks so far.     Upcoming By the next log I hope to have some polishing done such as have scriptable objects to make the data configurable. Add a startup class to initialize my state. Add a boost particle effect during jumps.

Treader

Treader

 

Dev Log #2

Intro This has been a long time coming unfortunately the last two weeks have been too busy with long nights and missed weekends I have fallen behind on this project. The framework is however ready and very minimum UI functionality is done as well. Unlike the previous dev log this will be code heavy with no images. Editor So first things first I decided to make the main scene into a single asset bundle and then load it into the game at runtime This script is pretty self explanatory it just builds a bundle and puts it in the StreamingAssets folder. using UnityEditor; using System.IO; public class CreateAssetBundles { [MenuItem("Assets/Build AssetBundles")] static void BuildAllAssetBundles() { string assetBundleDirectory = "Assets/StreamingAssets"; if (!Directory.Exists(assetBundleDirectory)) { Directory.CreateDirectory(assetBundleDirectory); } BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows); } }   Framework This is my framework lot of it has been brought in from my previous project. Async Bundle Loader The below script simply loads the asset bundle and only the asset bundle and not any asset that is inside the bundle so far I haven't needed that functionality so I haven't added it in. When the need arises I will add that in as well. This is really where I started experimenting with loading assets in co-routines to avoid mini freeze. using System.Collections; using UnityEngine; using System; using System.IO; public class AsyncBundleLoader : MonoBehaviour { Action<bool, UnityEngine.Object> OnResourceLoaded; public static AsyncBundleLoader instance; string path; private void Start() { instance = this; } //Only loads the assetbundle not an asset inside the bundle public void LoadBundle(string path, Action<bool, UnityEngine.Object> callback) { OnResourceLoaded = callback; this.path = path; StartCoroutine(StartAsyncLoad()); } IEnumerator StartAsyncLoad() { var bundleLoadRequest = AssetBundle.LoadFromFileAsync(Path.Combine(Application.streamingAssetsPath, path)); yield return bundleLoadRequest; AssetBundle myLoadedAssetBundle = bundleLoadRequest.assetBundle; if (myLoadedAssetBundle == null) { Debug.LogError("Failed to load AssetBundle at path: "+path); OnResourceLoaded(false, null); yield break; } OnResourceLoaded(true, myLoadedAssetBundle); myLoadedAssetBundle.Unload(false); } } Scene Loader This class was mainly for me to load my scene asynchronously after the scene bundle is loaded so the loading begins in the startup scene then once the scene is loaded we move into it this prevents any chance of the game getting suck while its loading. using System.Collections; using UnityEngine; using UnityEngine.SceneManagement; public class SceneLoader : MonoBehaviour { const string path = "mainscene"; AssetBundle mainSceneBundle = null; void Update() { // Press the space key to start coroutine if (Input.GetKeyDown(KeyCode.Space)) { // Use a coroutine to load the Scene in the background AsyncBundleLoader.instance.LoadBundle(path, HandleMainSceneLoaded); } } private void HandleMainSceneLoaded(bool isLoaded, UnityEngine.Object inObj) { if (isLoaded) { mainSceneBundle = inObj as AssetBundle; StartCoroutine(LoadYourAsyncScene()); } else { Debug.LogError("Failed to load the main scene"); } } IEnumerator LoadYourAsyncScene() { string path = mainSceneBundle.GetAllScenePaths()[0]; AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(path); // Wait until the asynchronous scene fully loads while (!asyncLoad.isDone) { yield return null; } } }   State Base This is the parent class to every State logic class this mainly defines the signature of the state and dosent contain any implementation of its own I considered using interface for a signature but the implementation I had in mind required references to be added from inspector and you cant do that without Monobehaviour. using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Treader { public abstract class StateBase : MonoBehaviour { public string stateName; // Use this for initialization public virtual void Init() { } public virtual void DeInit() { } } } States This is a convenience class  to maintain and access the state names. using System.Collections; using System.Collections.Generic; using UnityEngine; public class States { public const string MAIN_MENU_STATE = "MainMenu"; public const string GAMEPLAY_STATE = "Gameplay"; } FSM This is the main state class responsible for handling  the state change. using System.Collections.Generic; using UnityEngine; namespace Treader { public class TreaderFSM : MonoBehaviour { [SerializeField] List<StateBase> stateBases; [SerializeField] string defaultState; private static TreaderFSM instance; private StateBase currentState; public static TreaderFSM Instance { get { return instance; } private set { instance = value; } } public void Awake() { instance = this; if (!string.IsNullOrEmpty(defaultState)) { ChangeState(defaultState); } } public void ChangeState(string stateName) { for (int i = 0; i < stateBases.Count; i++) { if (stateBases[i].stateName.Equals(stateName)) { if (currentState != null) { currentState.DeInit(); } currentState = stateBases[i]; currentState.Init(); } } } } } Gameplay Currently there isint much here so far I only have the state logic class setup. Which at this point is nothing but an empty class that inherits from StateBase. UI Buttons So I am not going to be using the unity's button script mainly since I dont want button click functionality for this game so I will be writing my own button classes. IButton Each button class will inherit from this interface the purpose is so that I can use the OnButtonSelect function of the button without needing a reference to the specific button class. namespace Treader.UI { public interface IButton { void OnButtonSelect(); } } Start Button Currently the start button only changes the state and in all fairness that should really be all it should need to do. using UnityEngine; using Treader.UI; using Treader; public class StartButton : MonoBehaviour, IButton { public void OnButtonSelect() { TreaderFSM.Instance.ChangeState(States.GAMEPLAY_STATE); } }   Main Menu While the main menu has been visually set up its a good deal away from being done for now the State logic and UI class for the main menu have been setup.   Main Menu Logic This is the class that is responsible for handling all the defining what happens when a state changes to and from the MainMenu. Currently its just enables and disable the ui/ using Treader; using UnityEngine; public class MainMenuLogic : StateBase { [SerializeField] UiMainMenu mainMenu; public override void Init() { base.Init(); mainMenu.gameObject.SetActive(true); } public override void DeInit() { base.DeInit(); mainMenu.gameObject.SetActive(false); } }   UI Main Menu This class is responsible for the visuals of the main menu currently it handles registering the buttons and highlighting the selected button. using System.Collections.Generic; using Treader.UI; using UnityEngine; using Treader; public class UiMainMenu : MonoBehaviour { [SerializeField] GameObject[] buttonsGameObjects; [SerializeField] Transform selector; List<IButton> buttons; int selectedIndex = 0; // Use this for initialization void Start () { buttons = new List<IButton>(); RegisterButtons(); UpdateSelector(0); } void RegisterButtons() { buttons.Clear(); if (buttonsGameObjects != null) { for (int i = 0; i < buttonsGameObjects.Length; i++) { IButton button; button = buttonsGameObjects[i].GetComponent<IButton>(); Debug.Assert(button != null, "Failed to add buttons please makes sure all buttons inherit from IButton"); if (button != null) { buttons.Add(button); } } } } void UpdateSelector(int index) { if (index < buttonsGameObjects.Length) { selector.position = buttonsGameObjects[index].transform.position; selectedIndex = index; } } private void Update() { if (Input.GetKeyDown(KeyCode.X)) { buttons[selectedIndex].OnButtonSelect(); } } }   Utilities Last but not least the utility classes these are classes that help with very specific things that are common such as following a transform or keeping an object persistent. While there are other utility classes than the one I am mentioning here since they are not being used currently I am leaving them out for the time being.   Persist Object This class simply marks the object its attached to persistent which keeps the object between scenes. using UnityEngine; //Simple helper component class to keep the game object in scene public class PersistObject : MonoBehaviour { private void Awake() { DontDestroyOnLoad(this.gameObject); } }   Upcoming The next devlog will be when my first sprint is done I should have the character control done as well as some basic obstacles functional so the next dev log should have a mix of code and images.

Treader

Treader

 

Dev Log #1

Intro Its been little over a week since I started this project. So far I have setup the Bitbucket and sprint on Trello and Ollert so my planning and version control seems solid. Aside from that I have finished some other things I will list down. So far it seems I am ahead of track despite my bumpy progress, currently no lines of code have been written but that is high on the todo. Splash Screen This was really tricky not being an artist myself I had go to search for ready made templates I could use all sites I found usually charge a registration fee which for the scope of the current project seemed too high maybe some other time. So I did the next best thing loaded up Gimp watched a few youtube tutorials got some fancy text going added a bit of highlight and I have a splash screen logo ....is it as good as the templates found on other sites not by a long shot but it will do. Loading Screen To do this I had to first get a UI kit from the unity asset store I found I nice old school themed one which I think works well for that I have planned. The loading screen main purpose is really just to wait for the main scene to load initially I was planning on having it load individual assets but in hind sight those will load too fast for the loading screen to be of any use given the scope of the game but who knows the future may prove me wrong and I might still do this. So far the loading screen will mostly be a fake one going from 1-90 then stopping to wait till everything is loaded then moving to a 100% that is if everything hasent already loaded in which case it will fill directly to 100. Main Menu Initially I was planning on implementing the main menu but if I want to have a transparent main menu with game running in the background but without the player character present. So I have pushed the main menu implementation to the last since I need to get the basic game play done first. The UI however is done and setup the buttons will not be mouse clickable and instead will use arrows keys to select them and action to trigger.   Upcoming For the next dev log I should have the FSM and loading and building asset bundles ready that should be more code heavy while this one was image heavy.

Treader

Treader

 

Dev Log #0

Description So its been a few days since I finished my last project time to pick up a new one I have decided to make an infinite runner game similar to the no connection dinosaur game in your chrome web browser. The idea is to have a good music with tense game-play kinda like flappy bird but maybe not that hard and relaxing background. This is the first dev log made before the project starts hence nothing to show currently no images and such I will be adding those in future updates once I get the project started.    Feature List Game Play Basic 2D character movements left, right and up (jump) Double Jump  Power Jump Moving pillars that can push you back and also move up and down Randomly placed spikes that can kill you if you touch them Basic 2D run and jump animation Projectiles that move from left to right and can kill you UI Splash Screen Loading Screen Main Menu Instructions screen High score Screen About Us (Maybe if I think I have something to put in here ..maybe a link to the previous project) Options menu with sound and music toggle End screen In Game HUD   Back End Get and Set high score   Now that I am actually typing all this out it does seems like a lot but I have found that doing things one sprint at a time helps maintain motivation and its pretty cool to see a nice progress graph. I will either do these every week or every sprint havent decided that yet I figure I will have a better idea of how often to do these once I get started.

Treader

Treader

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!