Search Unity

RTS Tips: Keeping track of resources/players.

Discussion in 'Multiplayer' started by MTracerStudios, Sep 8, 2010.

  1. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    I need some help with ma rts. I need some help with where to start in terms of engaging units. (Very basic, but not sure what to do none the less.)

    Ok, so units can be selected and moved already. A selected unit is noted by a different base hue on it's material and a boolean variable set to "True" in one of it's scripts. Both friendly and enemy units can be selected. Only friendly units can be group selected.

    Here's the functionality which I need.

    1. Units need to target and fire at enemies within their attack radius when at rest. Units also need to stop firing at a target when it either dies or leaves their attack radius. Keep in mind that all units are mere gameobjects owned by either the serverplayer or the clientplayer.

    2. I need to generate a list of enemies for each unit to attack. Basically, with a group of friendly units selected, I want to click (not select) enemy units to add them to the targeting queue. The units will target the next enemy on the list as soon as the current one either dies or gets out of range. This list should stay with a unit until all members of said list are dead, or until the player targets a new set of enemies.

    ****In a nutshell****

    I wish to somehow link my units to specific enemy units to keep track of their positions and deaths.

    ****In a nutshell****

    Thanks,

    MTracer.
     
  2. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    bump. Can someone help me?!? :?
     
  3. mVlipka

    mVlipka

    Joined:
    Jun 2, 2010
    Posts:
    42
    Use an overlapping sphere to find if the enemies are within the specified distance. If they are, use an A* algorithm to calculate a path to take to get to them (there is a fabulous addon to Unity for A*). To stop firing, just remove their firing script, or set something like "dead = true" and then check if theyre dead when the fire method (or however you have it setup) is called.

    To do a order queue, make a list (I don't know how in Javascript)
    List<Orders> list = new List<Orders>()
    You can then make a class with the different orders, so say the list contains
    {Move, Move, Attack}
    Whenever the player finishes a order, you delete it from the list.

    I gave you a very basic outline on how to do things, you can contact me if you need help.
     
  4. ackyth

    ackyth

    Joined:
    Oct 29, 2009
    Posts:
    146
  5. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    Well, I guess I'm not looking for AI, I'm looking for how to do a basic character function within unity.
     
  6. ackyth

    ackyth

    Joined:
    Oct 29, 2009
    Posts:
    146
    Besides player input its all ai (numbercrunching, infogathering, and desiding what needs to be done). 8)

    For this you will need a list of nereby unit pointers.


    You will need a Master list of all units in your game.

    List that every unit has.
    Code (csharp):
    1.     public class TargetingData
    2.     {
    3.         public Unit target;
    4.         public float distance;
    5.     }
    6.  
    7.     public List<TargetingData> listOfTargets = new List<TargetingData>();
    and then I run this every few frames when I wish to update the info each ai uses.

    This has more checks then you really need. Only need the distance check andthe side check if you dont have a master list for each players units.
    Code (csharp):
    1.  
    2.     public void CheckForTargets()
    3.     {
    4.         listOfTargets.Clear();
    5.         foreach (Unit unit in gameMasterScript.masterUnitList)
    6.         {
    7.             if (unit.unitSide != thisUnit.unitSide  unit.stateMachine.actionState != StateMachine.FSM.death)
    8.             {
    9.                 float distanceToUnit = Vector3.Distance(transform.position, unit.transform.position);
    10.                 if (distanceToUnit < targetingRange)
    11.                 {
    12.                     if (unit.unitSide != thisUnit.unitSide  unit.unitAttackable == true)
    13.                     {
    14.                         TargetingData tempTarget = new TargetingData();
    15.                         tempTarget.target = unit;
    16.                         tempTarget.distance = distanceToUnit;
    17.  
    18.                         listOfTargets.Add(tempTarget);
    19.                     }
    20.                 }
    21.             }
    22.         }
    23.     }
    You could do the above with colliders detecting nereby units but I perfer the code, less setup and easyer to change.

    And when runing the ai state check if the pointer != null. If its null then have the ai switch back to idle state.

    Get a pointer to the unit you want to attack.

    Then add a que list to your units and add a target to it, then when the unit changes back to idle state have it look at the que list and if its > 0 then add quelise[0] to the current target of the unit.
     
  7. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    Okay, so I've decided to do a complete rewrite, and I've come into some fairly serious issues. How do I deal with different players units on the map? The units need to know if they are owned by the player interacting with them, but I can't just use NetworkView.isMine because that won't work for single player campaign/non-networked games.

    Please help!

    PS: I have a resourceManager in my game that is not instantiated over the network, so only the owning player can see it, this is probably not the best approach, as it would not work for single player games.
     
  8. ackyth

    ackyth

    Joined:
    Oct 29, 2009
    Posts:
    146
    Just use a int and have a function that gets a ID# for each player as the game starts.

    Also helps to have a TeamIDNumber too if its not a FreeForAll game.

    Im using a playerinput script that controls all the player input from keys and handles selection of units and other stuff, just added a int playerIDNumber to it thats uniqe for the player and everything checks that number so you can only order your own units around.

    ^^ Playerinput script works nicely for geting ai to work since the functions the playerinputscript calls can be called by the ai too.



    (Singleplayer <--> Multiplayer) is hard to code for have not done alot on it yet. But I have tryed this and it works so far.

    Code (csharp):
    1.  
    2.         if (Network.peerType == NetworkPeerType.Disconnected)
    3.         {
    4. //run singleplayer code.
    5.             PlayThis_Animation("idle");
    6.         }
    7.         else
    8.         {
    9. //run multiplayer code.
    10.             networkView.RPC("PlayThis_Animation", RPCMode.All, "idle");
    11.         }
    12.  
     
  9. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    Okay, I'm sorry, but you'll have to repeat yourself.

    Do I use a resource manager?
    What is this "PlayerID"?
    What gameobject is the playerinput script on, what does it do, and does it work for network players, single players and NPCs?
    What should the general architecture of my game logic be?
    Should I have each unit handle it's own business, and check the resourcemanager?
    Should I have all units controlled by a central gameobject, one per player?
    How should I handle buildings?
    How should non-networked/single player/campaign/NPC's be handled?

    Note: I'm not going to be handling NPC's at the moment, I'm shooting for a free online multiplayer demo. Is this the right approach? Should I go for free online campaign, and have people purchase the multiplayer?

    Sorry for all the questions, but I'm a complete noob.
     
  10. ackyth

    ackyth

    Joined:
    Oct 29, 2009
    Posts:
    146
    PlayerID is just a "int" when a player joins its assigned a number player1, player2, ext. all units that player creates get the id number of the player. When the player clicks on a unit it checks the number the unit has vs the players number to tell if they own the unit.

    Playerinput is just a script thats attached anywhere (usealy to the camera of the player) that holds all input commands (mousebutton downs, key presses) and contains pointers to the current selection of units.

    When a player hits a key it loops though all the selected units and runs a function on each of the units (Like Move,Attack,Stop ext).


    My Games "architecture" I got from "Game Coding Complete" Seems to work ok.
    breaks down into these 3

    GameLogic
    All code for runing the game and the "gameplay" stuff.

    PlayerInput (AI has its own playerinput script)
    All input a player can do (clicking on stuff, keys ext)

    GameView
    What the player sees when playing.

    This lets me keep stuff together yet easy to change one part without having to hunt down all the pointers.

    Yes and No, Think of it like a command structure the guys at the top dont need to know how to load a gun they just point troops in a direction and say "get'em boys". And the grunts dont need to know the grand strategy since they are commanded to go somewhere by the higher ups.

    When debugging you would have to hunt down all the random keypresses and other functions in a dozen scripts, if its all in one place and calls functions on the units its alot easyer to hunt stuff down.

    Could do a interface to your units and buildings and ask that if its a unit or building and have pointers there or just have buildings with the move command blank (can still give them move orders but it willnot run anything).

    Way i have it right now is:

    Agent (All basic commands and functions)
    --> AgentSpecial (inherit all the functions of agent but change a few that you need to get the result you want)

    As they all inherit from agent I can just use agent vars and it works for all, Though if you had a special command for another unit you need to put the virtual function in agent so that it knows of it.

    Not that far yet but maybe like bizzard (starcraftII) did, work on it till you get nere the polishing stage then break it into singleplayer and multiplayer stats.

    NPCs can use a AIinputscript that calls the same commands as the player can, it would play the same way but get info in a diffrent way.

    That is down to how you wish to publish your game, I am still working on my 1st game so I have no advice there.

    Time, Books, and Google will fix that :twisted:
     
  11. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    How exactly do I script a list of units for use from the master gameObject?

    BTW: that post was awesome!!!!!!!!!
     
  12. ackyth

    ackyth

    Joined:
    Oct 29, 2009
    Posts:
    146
    http://unity3d.com/support/documentation/ScriptReference/Component.GetComponent.html

    Or Use static var.

    Code (csharp):
    1.  
    2. //Using generic so that I can use List<>;
    3. using System.Collections.Generic;
    4. public class MasterGameScript : MonoBehaviour {
    5.  
    6. //Here I use a static var so that my other scripts can use it (I used to use getcomponent but got tired of adding it to everyscript)
    7.     public static MasterGameScript s_MasterGameScript;
    8. //List of units (From all sides)
    9.     public List<Agent> masterUnitList = new List<Agent>();
    10.  
    11. //Assign the static var.
    12.     void Awake()
    13.     {
    14.         s_MasterGameScript = this;
    15.     }
    16. }
    17.  
    Then I call it by:
    MasterGameScript.s_MasterGameScript.masterUnitList

    When a unit spawns add it to the masterlist
    Code (csharp):
    1.  
    2. void Start(){
    3. MasterGameScript.s_MasterGameScript.masterUnitList.Add(this);
    4. }
    5.  
    Just make sure the units add to the list in Start and the master var is setup in Awake or you may get a null pointer.
     
  13. MTracerStudios

    MTracerStudios

    Joined:
    Aug 24, 2010
    Posts:
    118
    I'm using javascript, are you? Cause "Using" Isn't working.
     
  14. ackyth

    ackyth

    Joined:
    Oct 29, 2009
    Posts:
    146
    C# But this would work with any array type or variable.
    I only know a small amount about unityscript so i dont know if it can use generics.

    List<> is just a defined array so it runs faster.

    Link with info for arrays in unity:
    http://www.unifycommunity.com/wiki/index.php?title=Which_Kind_Of_Array_Or_Collection_Should_I_Use?

    Just use one of the unityscript arrays and remove using System.Collections.Generic; and change void to function and it should work also the variables are in a diffrent order but i forget how to fix them.