Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Games Battlecruiser

Discussion in 'Works In Progress - Archive' started by Pixeye, Apr 18, 2017.

  1. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195


    The Battlecruiser is a game about building a gigantic space battleship from scraps. Construct, adapt and protect your mothership to fly away from dying world.



    Game site
    Facebook page
    Dev log

    Watch me making the game on Twitch

    Hi everyone: ) I've decided to start the diary about the game I develop. It's an experiment minimalistic game and I will share my experience of creating a game from scratch and cover up pitfalls I encounter.
     
    Last edited: Nov 3, 2017
    LudiKha, Billy4184, pcg and 1 other person like this.
  2. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
  3. SiliconDroid

    SiliconDroid

    Joined:
    Feb 20, 2017
    Posts:
    302
    Hi,

    Your game idea sounds fun, I love space!

    Well you bared your code so I had to look...:rolleyes:...

    Personally I would not make a state handling baseclass, state handling is so thin and low level that baseclassing it has no merits.

    Also beware of using string literals for state IDs. It's OK when you're in the thick of devving that project but say you revisit it in a few years, it's a real drag to remember and hunt out the names plus you could introduce human error with typo. It's better to use const ints or enums and take advantage of intellisense in vis studio to quickly peruse available states.

    Personally I love enums because you can also log them out raw and get the string name of the enum right in the log. Here's one of my stated scripts using enum, example of logging included.

    Code (CSharp):
    1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    2. //   ____ ___ _     ___ ____ ___  _   _   ____  ____   ___ ___ ____
    3. //  / ___|_ _| |   |_ _/ ___/ _ \| \ | | |  _ \|  _ \ / _ \_ _|  _ \
    4. //  \___ \| || |    | | |  | | | |  \| | | | | | |_) | | | | || | | |
    5. //   ___) | || |___ | | |__| |_| | |\  | | |_| |  _ <| |_| | || |_| |
    6. //  |____/___|_____|___\____\___/|_| \_| |____/|_| \_\\___/___|____/
    7. //
    8. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    9. using System.Collections;
    10. using System.Collections.Generic;
    11. using UnityEngine;
    12.  
    13. namespace SiliconDroid
    14. {
    15.     ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    16.     //    CLASS: obj_mechLaser
    17.     public class obj_mechLaser : SD_MonoBehaviour
    18.     {
    19.  
    20.         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    21.         //    CONSTANTS
    22.         const float K_BEAM_LENGTH = 1000.0f;
    23.         const float K_BEAM_WIDTH = 0.5f;
    24.         const float K_BEAM_Z_RELIEF = 0.5f;
    25.  
    26.         enum STATE
    27.         {
    28.             IDLE,
    29.             FIRE,
    30.             FIRING,
    31.             STOP,
    32.         }
    33.  
    34.         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    35.         //    WORKING DATA
    36.         private class WORKING_DATA
    37.         {
    38.             public Renderer oRendererMuzzle = null;
    39.             public Renderer oRendererBeam = null;
    40.             public Renderer oRendererEnd = null;
    41.  
    42.             public Transform tMuzzle = null;
    43.             public Transform tBeam = null;
    44.             public Transform tEnd = null;
    45.  
    46.             public lib_mesh_uv_animator cAnimatorMuzzle = null;
    47.             public lib_mesh_uv_animator cAnimatorEnd = null;
    48.  
    49.             public STATE eState = STATE.IDLE;
    50.         }
    51.         WORKING_DATA v = new WORKING_DATA();
    52.  
    53.         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    54.         //    UPDATE
    55.         void Update()
    56.         {
    57.             //---------------------------------------------------------------------------------------------------------------------
    58.             //    IDLE
    59.             if (v.eState == STATE.IDLE)
    60.             {
    61.                 return;
    62.             }
    63.             //---------------------------------------------------------------------------------------------------------------------
    64.             //    FIRE START
    65.             else if (v.eState == STATE.FIRE)
    66.             {
    67.                 //EXAMPLE OF LOGGING AN ENUM STATE:
    68.                 UnityEngine.Debug.Log("STATE IS NOW: " + v.eState);
    69.                 //EXAMPLE OF LOGGING AN ENUM STATE:
    70.                 UnityEngine.Debug.Log("STATE IS NOW: " + STATE.FIRE);
    71.                 //BOTH ABOVE GIVE SAME LOG OUTPUT: "STATE IS NOW: FIRE"
    72.            
    73.                 SetVisible(true);
    74.                 ClockBeam();
    75.                 v.eState = STATE.FIRING;
    76.             }
    77.             //---------------------------------------------------------------------------------------------------------------------
    78.             //    FIRING
    79.             else if (v.eState == STATE.FIRING)
    80.             {
    81.                 ClockBeam();
    82.             }
    83.             //---------------------------------------------------------------------------------------------------------------------
    84.             //    FIRE STOP
    85.             else if (v.eState == STATE.STOP)
    86.             {
    87.                 SetVisible(false);
    88.                 v.eState = STATE.IDLE;
    89.             }
    90.         }
    91.         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    92.         //   ____  _   _ ____  _     ___ ____   ___ _   _ _____ _____ ____  _____ _    ____ _____
    93.         //  |  _ \| | | | __ )| |   |_ _/ ___| |_ _| \ | |_   _| ____|  _ \|  ___/ \  / ___| ____|
    94.         //  | |_) | | | |  _ \| |    | | |      | ||  \| | | | |  _| | |_) | |_ / _ \| |   |  _|
    95.         //  |  __/| |_| | |_) | |___ | | |___   | || |\  | | | | |___|  _ <|  _/ ___ \ |___| |___
    96.         //  |_|    \___/|____/|_____|___\____| |___|_| \_| |_| |_____|_| \_\_|/_/   \_\____|_____|
    97.         //
    98.         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    99.  
    100.         ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    101.         //    FIRE START/STOP
    102.         public void Fire(bool bFire)
    103.         {
    104.             if (bFire)
    105.             {
    106.                 v.eState = STATE.FIRE;
    107.             }
    108.             else
    109.             {
    110.                 v.eState = STATE.STOP;
    111.             }
    112.         }
    113.         //TRUNCATED FOR POST BREVITY
    114.  

    NOTE: Baseclassing IS cool and it's nice to see you working with it:cool:, but I would wait for a thicker gob of common logic or required functionality to rear its head as your game progresses.

    EDIT:
    http://btlcruiser.com/ site... ship GFX banner FTW!
     
    Last edited: Apr 26, 2017
    Pixeye likes this.
  4. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    I love enums too! But decided to write this part as much generic as possible: ) Thanks for sharing your code though, I find your approach totally acceptable for me: )
     
    SiliconDroid likes this.
  5. MMOInteractiveRep

    MMOInteractiveRep

    Joined:
    Apr 7, 2015
    Posts:
    88
    SiliconDroid's approach tends to be similar to how I handle state machines as well only instead of the If Elseif statements I use a switch statement. Ideas similar to these are the easiest and fastest ways to get a State Machine up and running.

    Looking forward to seeing how your project goes from here! Keep up the good work!
     
  6. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    The battlecruiser is built from the small platforms. Player connects them to each other by dragging free platforms from space.





    Player sends little probes to rip new platforms from space garbage : )

     
    Last edited: Apr 28, 2017
    SiliconDroid likes this.
  7. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    Building up the battlecruiser from platforms!

    https://i.gyazo.com/799db9c3c84bd6118c3e1c8ead0f744b.mp4

    I needed a random pick to spawn platforms with different amount of pins. There is a useful trick to make some random pick up. ( Well, mostly everyone knows how to do it, but I'll post for the beginners )

    Code (CSharp):
    1.  public static class ExtensionMethods
    2. {
    3.   static System.Random _r = new System.Random();
    4.  
    5. public static int ReturnRandom(this float[] probs)
    6.   {
    7.    float total = 0f;
    8.    for (int i = 0; i < probs.Length; i++)
    9.     total += probs[i];
    10.    float RandomPoint = (float)_r.NextDouble() * total;
    11.    for (int i = 0; i < probs.Length; i++)
    12.    {
    13.     if (RandomPoint < probs[i])
    14.      return i;
    15.     else
    16.      RandomPoint -= probs[i];
    17.    }
    18.  
    19.    return probs.Length - 1;
    20.   }
    21. }
    Now you can do something like this:

    Code (CSharp):
    1.  int sidesAmount = new float[4] { 50f, 25f, 18.5f, 6.5f }.ReturnRandom();

    The idea is that only linked to "reactor" node platforms will be active. So I had to do some checkings if our platforms can reach the main node from a chain of connections.



    With 4 sided platforms we can easily check neighbors for active pins. So the pin indexed 1 will refer to pin 3 from the right sided neighbor.

    At first, I used the method from screen, but there is an alternative way to get pin index : )
    Code (CSharp):
    1.  for(int i = 0; i < 4; i++)
    2. {
    3. index = (i + 2) % 4
    4. }
     
    theANMATOR2b and SiliconDroid like this.
  8. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    I like the way price is shown in another brilliant game, Kingdom: New lands.



    I made a script to generate price nodes in nice looking rows with some "arc" effect. Feel free to take it if needed or maybe you can see how to improve it ; )

    Code (CSharp):
    1. [SerializeField]
    2.        private int currentPrice = 0;
    3.        [SerializeField]
    4.        private float size = 1.0f;
    5.        [SerializeField]
    6.        private Transform[] nodeObjs;
    7.        [SerializeField]
    8.        private float arcSize = 0.1f;
    9.        [SerializeField]
    10. /// <summary>
    11.        /// Bad in math. Good in bed.
    12.        /// </summary>
    13.        void CalculateNodes()
    14.        {
    15.            // Add nodes to array with we will work
    16.            Transform[] nodes = new Transform[currentPrice];
    17.            for (int i = 0;i<nodeObjs.Length;i++)
    18.            {
    19.                nodeObjs[i].gameObject.SetActive((i<currentPrice)?true:false);
    20.                if (currentPrice>i)
    21.                nodes[i] = nodeObjs[i];
    22.            }
    23.            // we will calculate single row length based on amount of price nodes.
    24.            int rowLength = currentPrice / 2;
    25.            if (currentPrice < 7)
    26.                rowLength = currentPrice;
    27.            float zPos = 0;
    28.            float extraOffset = 0;
    29.  
    30.            for (int i = 0; i < currentPrice; i++)
    31.            {
    32.                float offset = 0;
    33.                float arcRatio = 0;
    34.                float yHeight = 0;
    35.        
    36.      
    37.                if (i < rowLength)
    38.                {
    39.                    zPos = size * 1.25f;
    40.                    extraOffset = 0;
    41.                    if ((rowLength % 2) == 0)
    42.                        extraOffset = size * 0.5f;
    43.                    offset = (rowLength / 2 * size - extraOffset) * -1;
    44.                    arcRatio = Mathf.PingPong((float)i / (float)(rowLength-1), 0.5f);
    45.                }
    46.                else
    47.                {
    48.                    zPos = 0;
    49.                    extraOffset = 0;
    50.                    if (((currentPrice - rowLength) % 2) == 0)
    51.                        extraOffset = size * 0.5f;
    52.                    arcRatio = Mathf.PingPong((float)(i-rowLength) / (float)(currentPrice-rowLength-1), 0.5f);
    53.                    offset = ((rowLength*size) + ((currentPrice-rowLength) / 2 * size - extraOffset)) * -1 ;
    54.                }
    55.                yHeight = Mathf.Sin(arcRatio * Mathf.PI)*arcSize;
    56.                nodes[i].localPosition = new Vector3(offset + i * size, yHeight, -zPos);
    57.            }
    58.        }
     
  9. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    The final process of buying anything in the game. Right now you get the structure immediately, but you will need special drones in future to build turrets.

     
  10. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    been a while since I've updated the thread. I've implemented a lot of stuff to game.
    Modules on platforms :

    Reactor module - the heart of the ship. All other modules links to the reactor. If the link chain breaks the module goes
    inactive untill the chain restored.
    Drone bay - you can excange one of your probe to builder drone. Drones construct other modules.
    Energy shield module - an energy shield that can be filled 4 times. Protects nearby modules from attacks.
    Turret - kills everything suspicious : )

    I've also added enemies. They spawn around your big ship and try to destroy reactor module. They can choose target based on special "threat" level.

    The last adding is the Battlecruiser itself. The Battlecruiser is divided in 5 huge decks with slots to fill with platforms u find in space. Right now I've added the "main" deck.

     
    Last edited: May 15, 2017
    NickHaldon likes this.
  11. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195


    I've recorded a video to show the summary of work I've done til today.


    Also, if you are interested in simple shader that colors specific parts of a model feel free to take it from my blog



    or copy/paste from here :

    Code (CSharp):
    1. Shader "Custom/CustomColorPainter" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _ColorEmission("ColorEmission", Color)=(1,1,1,1)
    5.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    6.         _EmissionMap ("EmissionMap",2D) = "gray" {}
    7.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    8.         _Metallic ("Metallic", Range(0,1)) = 0.0
    9.     }
    10.     SubShader {
    11.         Tags { "RenderType"="Opaque" }
    12.         LOD 200
    13.  
    14.         CGPROGRAM
    15.         // Physically based Standard lighting model, and enable shadows on all light types
    16.         #pragma surface surf Standard fullforwardshadows
    17.  
    18.         // Use shader model 3.0 target, to get nicer looking lighting
    19.         #pragma target 3.0
    20.  
    21.         sampler2D _MainTex;
    22.         sampler2D _EmissionMap;
    23.         struct Input {
    24.             float2 uv_MainTex;
    25.             float2 uv_EmissionMap;
    26.         };
    27.  
    28.         half _Glossiness;
    29.         half _Metallic;
    30.         fixed _AlphaChecker;
    31.         fixed4 _Color;
    32.         fixed4 _ColorEmission;
    33.  
    34.         // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    35.         // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    36.         // #pragma instancing_options assumeuniformscaling
    37.         UNITY_INSTANCING_CBUFFER_START(Props)
    38.             // put more per-instance properties here
    39.         UNITY_INSTANCING_CBUFFER_END
    40.  
    41.         void surf (Input IN, inout SurfaceOutputStandard o) {
    42.             _AlphaChecker = 0.6;
    43.  
    44.             fixed3 endColor = fixed3(0.0,0.0,0.0);
    45.             fixed4 ca = tex2D(_EmissionMap, IN.uv_EmissionMap);
    46.  
    47.  
    48.             // normalColor stuff
    49.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
    50.  
    51.  
    52.  
    53.             // emission stuff
    54.             if (ca.a<=_AlphaChecker){
    55.                 o.Emission = half3(0.0,0.0,0.0);
    56.  
    57.             endColor = c.rgb;
    58.             }
    59.             else{
    60.             o.Emission = _ColorEmission;
    61.             endColor = _ColorEmission;
    62.             }
    63.  
    64.             if (c.a<_AlphaChecker)
    65.             endColor = _Color;
    66.  
    67.  
    68.  
    69.             // Metallic and smoothness come from slider variables
    70.             o.Metallic = _Metallic;
    71.             o.Smoothness = _Glossiness;
    72.             o.Albedo = endColor.rgb;
    73.             o.Alpha = c.a;
    74.         }
    75.         ENDCG
    76.     }
    77.     FallBack "Diffuse"
    78. }
    79.  
    As you can see it's pretty easy and straightforward
     
    Last edited: May 26, 2017
    theANMATOR2b and mgsvevo like this.
  12. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195


    Hey ho! The second update of the Battlecruiser game where I talk about some utility scripts and simple shaders.

    I've also made a simple library for fading out groups of objects similar to canvas group but for any kind of objects, not only UI. About render group lib

     
  13. nicolasbulchak

    nicolasbulchak

    Joined:
    Aug 9, 2013
    Posts:
    37
    This is cool to see the progress as you move along. When did you start?
     
  14. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    Hey! I wrote a game prototype early this year but then I had to do some other stuff. I get back to work somewhere in ~10 of May

    Cheers
     
  15. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    In previous 2 months I was learning more cool stuff about unity:)

    The game looks much better and smoother now. As today is a #unitytip day I share a simple timer with delayed action. It is based on Unirx



    Feel free to download it from github
     
  16. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    I'm tired of managing scenes from scratch so I created little script that allows to automate the routine of creating new scenes. LIKE A SIR!





    Code (CSharp):
    1. /*===============================================================
    2. Product:    Unity3d Utilities
    3. Developer:  Dimitry Pixeye - pixeye@hbrew.store
    4. Company:    Homebrew - http://hbrew.store
    5. Date:       16/09/2017 01:51
    6. ================================================================*/
    7. // Add script to SceneManager/Editor/
    8. using UnityEditor;
    9. using UnityEditor.SceneManagement;
    10. using UnityEngine.SceneManagement;
    11. using UnityEngine;
    12. [InitializeOnLoad]
    13. public class SceneGenerator  {
    14.     static SceneGenerator()
    15.     {
    16.         EditorSceneManager.newSceneCreated += SceneCreating;
    17.     }
    18.     public static void SceneCreating(Scene scene, NewSceneSetup setup, NewSceneMode mode)
    19.     {
    20.    
    21.         var camGO = Camera.main.transform;
    22.         var lightGO = GameObject.Find("Directional Light").transform;
    23.    
    24.         var setupFolder = new GameObject("[SETUP]").transform;
    25.         var lights = new GameObject("Lights").transform;
    26.         lights.parent = setupFolder;
    27.         lightGO.parent = lights;
    28.         var cam  = new GameObject("Cameras").transform;
    29.         cam.parent = setupFolder;
    30.         camGO.parent = cam;
    31.         var world = new GameObject("[WORLD]").transform;
    32.         new GameObject("Static").transform.parent = world;
    33.         new GameObject("Dynamic").transform.parent = world;
    34.         new GameObject("[UI]");
    35.    
    36.         Debug.Log("New scene created!");
    37.     }
    38.  
    39. }
     
  17. AkiraWong89

    AkiraWong89

    Joined:
    Oct 30, 2015
    Posts:
    662
    Aha. Yeah. Me too.
    I need to turn off auto lightmap baking on each new scenes as I don't need them for example.
    I'm not a programmer so my way is to make empty scenes template and duplicate them.:D
     
  18. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    Well, adding that script will make your life easier : )

    I've added a pool manager feel free to download it for your projects. It's ultra fast and has prepopulate feature. It's using the Unirx plugin
     
    theANMATOR2b likes this.
  19. AkiraWong89

    AkiraWong89

    Joined:
    Oct 30, 2015
    Posts:
    662
    @pixeye
    Ya. Able to save time is always good even is one second.
    Cool. This should be very useful on bullet hell games like Touhou.
    Thanks for sharing. I will try it to make "rain" and dodge it.:D
     
  20. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    Finished with effect of ship power setup. You need to put shiny cube to reactor module .

     
    Sluggy and mgsvevo like this.
  21. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    The background of the game will be debris of our homeworld planet.

     
    FreakForFreedom and mgsvevo like this.
  22. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    I've made a time lapse for fun to show process of creating desolate planet on the background of the game.
    It was pretty tricky to show really huge scaled objects in the scene without weird glitches so I've ended up using second camera for my background.

    I use amplify shader editor and tools for post effecting.



     
    Sanhueza and FreakForFreedom like this.
  23. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    In the game, you will find some huge enemies, sort of bosses. The first one is a big spawning cruiser with portals to spawn swarms of little droids. He appears randomly and stays for a while, generating swarms. The warship armed with big turret gun and rockets. Rockets used when significant danger occurs and can destroy player's corvette with one hit. A player can stop this ship by destroying portals and modules on it.


    https://i.gyazo.com/b1542d485aefe89e813f2d8d061925fa.mp4
     
  24. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    Does the video in post #20 above represent the games lighting setup?
    If so - I think it looks interesting, it is kind of a muted look though with a directional in the scene to cast shadows. It's like how I would imagine space lighting to be (other than complete darkness if blocked from the sun) if there was an ambient light source. Looks cool!
     
  25. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    Thanks for the feedback : ) Video #20 post represents energy reactor setup. It's a "heart" of the battlecruiser and gives energy to all ship modules.

    About lightning setup in the scene - it's somewhat tricky and nonrealistic anyways. There will be two phases.
    Day ( when sun is "above" the ship ) and night ( when sun is "behind" the ship )

    So you will have a different mood in the game, and I plan that enemies will spawn and attack in the night phase.
     
    theANMATOR2b likes this.
  26. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    Hello Pilots! Currently, I'm working on the creation of a combat system. Your ship is not very strong and will not hold a lot of damage. The video below shows an example of a battle in the game.

    The other news is that I finally created a Discord channel for the game. I hope we will have a lot of fun there.

    Do you like the pace of fighting on video below?

     
    theANMATOR2b, Sanhueza and PhilippG like this.
  27. Pixeye

    Pixeye

    Joined:
    Jul 2, 2011
    Posts:
    195
    Things goes pretty slowly :) We are experementing with effects.



    Btw, if someone doesn't know, you can use lights with particles. For me, the best workflow is to make an empty prefab with light and attach it to your ps light folder. You can use the color of your ps for your light as well.

     
    PhilippG likes this.
  28. Ybs

    Ybs

    Joined:
    Jun 6, 2015
    Posts:
    4
    I like the effects. Looks promising :)
     
  29. Deleted User

    Deleted User

    Guest

    This is looking rather cool, well done..!