Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[UNITY 5 FPS Tutorials] GTGD S3 - Advanced First Person Shooter

Discussion in 'Community Learning & Teaching' started by GTGD, Oct 9, 2015.

  1. Goofy420

    Goofy420

    Joined:
    Apr 27, 2013
    Posts:
    248
    The only thing I can assume is that the problem originates in your Shooter script and is causing an infinite loop instead of return or break after you fire. Those two lines in themselves shouldn't be causing an issue. and since your degug isn't being called, you know that the stack calls before your debug code. Try to trace the stack if possible. If you have pause on error enabled, unpause it a few times and see if it displays any more errors, specifically from your player oor shooter code.
     
  2. OldVikingDaddy

    OldVikingDaddy

    Joined:
    Apr 18, 2016
    Posts:
    1
    Hi, I made an enemy according to gtgd videos. However, when I put the enemy detection script I keep getting;
    NullReferenceException: Tag: tag name is null.
    S3.Enemy_Detection.CarryOutDetection () (at Assets/Scripts/Enemy/Enemy_Detection.cs:59)
    S3.Enemy_Detection.Update () (at Assets/Scripts/Enemy/Enemy_Detection.cs:31)

    so the enemy can't detect the target (player)

    -I followed all the steps
    -player and enemy layered and tagged
    -the enemy can walk randomly but cannot detect the player in the enemy master script

    Can someone please help me?
    Thanks
     
  3. dalmroots

    dalmroots

    Joined:
    Feb 11, 2017
    Posts:
    1
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4.  
    5. namespace Chapter1
    6.  
    7. {
    8.  
    9.     public class WalkTroughWall : MonoBehaviour {
    10.  
    11.  
    12.         public void SetLayerToNotSolid()
    13.         {
    14.             gameObject.layer = LayerMask.NameToLayer("Not Solid");
    15.             GetComponent<Renderer> ().material.color = Color.green;
    16.         }
    17.  
    18.         public void SetLayerToDefault()
    19.         {
    20.             gameObject.layer = LayerMask.NameToLayer("Default");
    21.             GetComponent<Renderer> ().material.color = Color.white;
    22.         }
    23.     }
    24. }
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4.  
    5. namespace Chapter1
    6. {
    7.     public class TriggerExample : MonoBehaviour
    8.     {
    9.       private WalkTroughWall walkTroughWallScript;
    10.  
    11.         void start()
    12.         {
    13.             SetInitialReferences ();
    14.         }
    15.  
    16.         void OnTriggerEnter(Collider other)
    17.         {
    18.             walkTroughWallScript.SetLayerToNotSolid ();
    19.         }
    20.  
    21.         void OnTriggerExit(Collider other)
    22.         {
    23.             walkTroughWallScript.SetLayerToDefault ();
    24.         }
    25.  
    26.         void SetInitialReferences()
    27.         {
    28.             if(GameObject.Find("Wall")!=null)
    29.             {
    30.                
    31.                 walkTroughWallScript = GameObject.Find("Wall").GetComponent<WalkTroughWall> ();
    32.             }
    33.         }
    34.  
    35.  
    36.  
    37.     }
    38.  
    39.  
    40.  
    41. }
    42.  
    I just cant figure out this error ._.
     

    Attached Files:

    • bong.png
      bong.png
      File size:
      420.4 KB
      Views:
      940
  4. doppie320

    doppie320

    Joined:
    Feb 13, 2017
    Posts:
    7
    Hey GTGD, If you can reply i'll be thankful hat you helped, I got this error on Item_Pickup and i
    get this

    and C2 was now renamed to JemoScripting

    and here i got the script i wrote for the pickup:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace JemoScripting
    6. {
    7.     public class Item_Pickup : MonoBehaviour
    8.     {
    9.         private Item_Master itemMaster;
    10.         private Transform myTrans;
    11.  
    12.         void OnEnable()
    13.         {
    14.             SetInitialReferences();
    15.             itemMaster.EventPickupAction += CarryOutPickupActions;
    16.         }
    17.            
    18.         void OnDisable()
    19.         {
    20.             itemMaster.EventPickupAction -= CarryOutPickupActions;
    21.         }
    22.  
    23.         void CarryOutPickupActions(Transform tParent)
    24.         {
    25.             transform.SetParent(tParent);
    26.             itemMaster.CallEventObjectPickup();
    27.             transform.gameObject.SetActive(false);
    28.         }
    29.  
    30.         void SetInitialReferences()
    31.         {
    32.             itemMaster = GetComponent<Item_Master>();
    33.         }
    34.     }
    35.  
    36. }
    37.  
    38.  
    39.  
    for the master

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. namespace JemoScripting
    7. {
    8.     public class Item_Master : MonoBehaviour
    9.     {
    10.         private PlayerMaster playerMaster;
    11.  
    12.         public delegate void GeneralEventHandler();
    13.         public event GeneralEventHandler EventObjectThrow;
    14.         public event GeneralEventHandler EventObjectPickup;
    15.  
    16.         public delegate void PickupActionEventHandler(Transform item);
    17.         public event PickupActionEventHandler EventPickupAction;
    18.  
    19.         void OnEnable()
    20.         {
    21.             SetInitialReferences();
    22.         }
    23.  
    24.         public void CallEventObjectThrow()
    25.         {
    26.             if(EventObjectThrow != null)
    27.             {
    28.                 EventObjectThrow();
    29.                 playerMaster.CallEventHandsEmpty();
    30.                 playerMaster.CallEventInventoryChanged();
    31.             }
    32.         }
    33.  
    34.         public void CallEventObjectPickup()
    35.         {
    36.             if(EventObjectPickup != null)
    37.             {
    38.                 EventObjectPickup();
    39.                 playerMaster.CallEventInventoryChanged();
    40.             }              
    41.         }
    42.  
    43.         public void CallEventPickupAction (Transform item)
    44.         {
    45.             if(EventPickupAction != null)
    46.             {
    47.                 EventPickupAction(item);
    48.             }  
    49.         }
    50.  
    51.         void SetInitialReferences()
    52.         {
    53.             if(GameManager_References._player != null)
    54.             {
    55.                 playerMaster = GameManager_References._player.GetComponent<PlayerMaster>();
    56.             }
    57.         }
    58.     }
    59. }
    60.  

    and for the detection

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace JemoScripting
    6. {
    7. public class Player_Detection : MonoBehaviour
    8.     {
    9.        
    10.         public LayerMask layerToDetect;
    11.         public Transform rayTransformPivot;
    12.         public string buttonPickup;
    13.  
    14.         private Transform itemAvailableForPickup;
    15.         private RaycastHit hit;
    16.         public float detectRange = 3;
    17.         public float detectRadius = 0.7f;
    18.         private bool itemInRange;
    19.  
    20.         private float labelWidth = 400;
    21.         private float labelHeight = 100;
    22.    
    23.         void Update ()
    24.         {
    25.             CastRayForDetectingItems();
    26.             CheckForItemPickupAttempt();
    27.         }
    28.  
    29.         void CastRayForDetectingItems()
    30.         {
    31.             if (Physics.SphereCast(rayTransformPivot.position, detectRadius, rayTransformPivot.forward, out hit, detectRange, layerToDetect))
    32.             {
    33.                 itemAvailableForPickup = hit.transform;
    34.                 itemInRange = true;
    35.             }
    36.  
    37.             else
    38.             {
    39.                 itemInRange = false;
    40.             }
    41.         }
    42.  
    43.         void CheckForItemPickupAttempt()
    44.         {
    45.             if (Input.GetButtonDown(buttonPickup) && Time.timeScale > 0 && itemInRange && itemAvailableForPickup.root.tag != GameManager_References._playerTag)
    46.             {
    47.                 itemAvailableForPickup.GetComponent<Item_Master>().CallEventPickupAction(rayTransformPivot);
    48.             }
    49.         }
    50.  
    51.         void OnGUI()
    52.         {
    53.             if (itemInRange && itemAvailableForPickup != null)
    54.             {
    55.                 GUI.Label(new Rect(Screen.width/2 - labelWidth/2, Screen.height/2, labelWidth, labelHeight), itemAvailableForPickup.name);
    56.             }
    57.         }
    58.     }
    59.  
    60. }
    61.  
    62.  
    63.  

    i had a little help from others but there's no solution, maybe you can find my error and reply out what went WRONG.


    Thank you.
     
  5. doppie320

    doppie320

    Joined:
    Feb 13, 2017
    Posts:
    7

    This will happen :/
    This pic was outdated it's actually JemoScripting now.

    I have the codes here

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace JemoScripting
    6. {
    7.     public class Item_Pickup : MonoBehaviour
    8.     {
    9.         private Item_Master itemMaster;
    10.  
    11.         void OnEnable()
    12.         {
    13.             SetInitialReferences();
    14.             itemMaster.EventPickupAction += CarryOutPickupActions;
    15.         }
    16.  
    17.         void OnDisable()
    18.         {
    19.             itemMaster.EventPickupAction -= CarryOutPickupActions;
    20.         }
    21.  
    22.         void SetInitialReferences()
    23.         {
    24.             itemMaster = GetComponent<Item_Master>();
    25.         }
    26.  
    27.         void CarryOutPickupActions(Transform tParent)
    28.         {
    29.             transform.SetParent(tParent);
    30.             itemMaster.CallEventObjectPickup();
    31.             transform.gameObject.SetActive(false);
    32.         }
    33.     }
    34.  
    35. }
    36.  
    37.  
    38.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. namespace JemoScripting
    7. {
    8.     public class Item_Master : MonoBehaviour
    9.     {
    10.         private Player_Master playerMaster;
    11.  
    12.         public delegate void GeneralEventHandler();
    13.         public event GeneralEventHandler EventObjectThrow;
    14.         public event GeneralEventHandler EventObjectPickup;
    15.  
    16.         public delegate void PickupActionEventHandler(Transform item);
    17.         public event PickupActionEventHandler EventPickupAction;
    18.  
    19.         void OnEnable()
    20.         {
    21.             SetInitialReferences();
    22.         }
    23.      
    24.         public void CallEventObjectThrow()
    25.         {
    26.             if(EventObjectThrow != null)
    27.             {
    28.                 EventObjectThrow();
    29.                 playerMaster.CallEventHandsEmpty();
    30.                 playerMaster.CallEventInventoryChanged();
    31.             }
    32.         }
    33.  
    34.         public void CallEventObjectPickup()
    35.         {
    36.             if(EventObjectPickup != null)
    37.             {
    38.                 EventObjectPickup();
    39.                 playerMaster.CallEventInventoryChanged();
    40.             }
    41.         }
    42.  
    43.         public void CallEventPickupAction(Transform item)
    44.         {
    45.             if(EventPickupAction != null)
    46.             {
    47.                 EventPickupAction(item);
    48.             }
    49.         }
    50.  
    51.         void SetInitialReferences()
    52.         {
    53.             if(GameManager_References._player != null)
    54.             {
    55.                 playerMaster = GameManager_References._player.GetComponent<Player_Master>();
    56.             }
    57.         }
    58.     }
    59. }
    60.  
    61.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace JemoScripting
    6. {
    7. public class Player_Detection : MonoBehaviour
    8.     {
    9.      
    10.         public LayerMask layerToDetect;
    11.         public Transform rayTransformPivot;
    12.         public string buttonPickup;
    13.  
    14.         private Transform itemAvailableForPickup;
    15.         private RaycastHit hit;
    16.         public float detectRange = 3;
    17.         public float detectRadius = 0.7f;
    18.         private bool itemInRange;
    19.  
    20.         private float labelWidth = 400;
    21.         private float labelHeight = 100;
    22.  
    23.         void Update ()
    24.         {
    25.             CastRayForDetectingItems();
    26.             CheckForItemPickupAttempt();
    27.         }
    28.  
    29.         void CastRayForDetectingItems()
    30.         {
    31.             if (Physics.SphereCast(rayTransformPivot.position, detectRadius, rayTransformPivot.forward, out hit, detectRange, layerToDetect))
    32.             {
    33.                 itemAvailableForPickup = hit.transform;
    34.                 itemInRange = true;
    35.             }
    36.  
    37.             else
    38.             {
    39.                 itemInRange = false;
    40.             }
    41.         }
    42.  
    43.         void CheckForItemPickupAttempt()
    44.         {
    45.             if (Input.GetButtonDown(buttonPickup) && Time.timeScale > 0 && itemInRange && itemAvailableForPickup.root.tag != GameManager_References._playerTag)
    46.             {
    47.                 itemAvailableForPickup.GetComponent<Item_Master>().CallEventPickupAction(rayTransformPivot);
    48.             }
    49.         }
    50.  
    51.         void OnGUI()
    52.         {
    53.             if (itemInRange && itemAvailableForPickup != null)
    54.             {
    55.                 GUI.Label(new Rect(Screen.width/2 - labelWidth/2, Screen.height/2, labelWidth, labelHeight), itemAvailableForPickup.name);
    56.             }
    57.         }
    58.     }
    59.  
    60. }
    61.  
    62.  
    63.  
    i'm pretty desperate
     
  6. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Hey JemoYT,

    The problem you are having sounds extremely similar to a problem I had early on in my project. I kept getting similar errors but couldn't track down the problem in my code. I kept poring over it, watching the videos again and again and getting frustrated because what I had looked correct.

    Now, what I'm about to tell you is going to sound really stupid, and tbh with you I still dont really understand what happened or why this fixed it but...

    What I did was go through each problem script and delete all the white space and re-space it... You see, I noticed that when I had done that to part of one of my scripts the error message moved down to a different line. So I redid the whole script and suddenly it worked fine.

    Don't ask me why it worked. I can only assume I had some kind of bug with my editor or something. I'm not sure if this is the same sort of problem you are having but its worth checking I guess.

    Anyway, I've written a few scripts to extend the player module a bit. I was hoping you guys might give me some feedback about optimizing them.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace G5
    6. {
    7.     public class Player_Crouch : MonoBehaviour
    8.     {
    9.  
    10.         public float crouchSpeed = 0.1f;
    11.         public float crouchHeight;
    12.         private CharacterController myCharacterController;
    13.         private float charHeight;
    14.         public bool isCrouched = false;
    15.         public bool hasCrouchToggle = true;
    16.         public string crouchButton;
    17.         private float heightInterval = 0.05f;
    18.         private Vector3 tempCenter;
    19.  
    20.         void Start ()
    21.         {
    22.             SetInitialReferences ();
    23.         }
    24.  
    25.         void Update ()
    26.         {
    27.             CheckForCrouchToggle ();
    28.         }
    29.  
    30.         void SetInitialReferences()
    31.         {
    32.             myCharacterController = GetComponent<CharacterController> ();
    33.             charHeight = myCharacterController.height;
    34.             InvokeRepeating ("Crouch", 0.0f, crouchSpeed);
    35.             tempCenter = myCharacterController.center;
    36.         }
    37.  
    38.         void CheckForCrouchToggle()
    39.         {
    40.             if(Input.GetButtonUp(crouchButton) && hasCrouchToggle)
    41.             {
    42.                 isCrouched = !isCrouched;
    43.             }
    44.             else if(!hasCrouchToggle)
    45.             {
    46.                 if (Input.GetButtonDown (crouchButton))
    47.                 {
    48.                     isCrouched = true;
    49.                 }
    50.                 else if (Input.GetButtonUp(crouchButton))
    51.                 {
    52.                     isCrouched = false;
    53.                 }
    54.             }
    55.         }
    56.  
    57.         void Crouch()
    58.         {
    59.             if(isCrouched && myCharacterController.height > crouchHeight)
    60.             {
    61.                 myCharacterController.height -= heightInterval;
    62.  
    63.                 if(myCharacterController.height < crouchHeight)
    64.                 {
    65.                     myCharacterController.height = crouchHeight;
    66.                 }
    67.             }
    68.             else if(!isCrouched && myCharacterController.height < charHeight)
    69.             {
    70.                 myCharacterController.height += heightInterval;
    71.  
    72.                 if(myCharacterController.height > charHeight)
    73.                 {
    74.                     myCharacterController.height = charHeight;
    75.                 }
    76.             }
    77.  
    78.             if (isCrouched && myCharacterController.center.y < crouchHeight / 2)
    79.             {
    80.                 tempCenter.y += heightInterval / 2;
    81.                 myCharacterController.center = tempCenter;
    82.  
    83.                 if(myCharacterController.center.y > crouchHeight / 2)
    84.                 {
    85.                     tempCenter.y = crouchHeight / 2;
    86.                     myCharacterController.center = tempCenter;
    87.                 }
    88.             }
    89.             else if(!isCrouched && myCharacterController.center.y > 0)
    90.             {
    91.                 tempCenter.y -= heightInterval / 2;
    92.                 myCharacterController.center = tempCenter;
    93.  
    94.                 if(myCharacterController.center.y < 0)
    95.                 {
    96.                     tempCenter.y = 0;
    97.                     myCharacterController.center = tempCenter;
    98.                 }
    99.             }
    100.         }
    101.     }
    102. }

    Here's a different crouch script. The one we have on the first page seemed kinda funky so I wrote a different one that has a little more functionality. The crouch height and speed is adjustable in the editor and there's a crouch toggle so people can choose whether they want to hold down crouch or just press it once.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. namespace G5
    7. {
    8.     public class Player_MiniMap : MonoBehaviour {
    9.  
    10.         private int toggleState = 1;
    11.         private Player_Master playerMaster;
    12.         public Transform miniMapCamera;
    13.         public Image miniMapPanel;
    14.         public string toggleMiniMapButton;
    15.      
    16.         void OnEnable ()
    17.         {
    18.             SetInitialReferences ();
    19.             playerMaster.EventMiniMapToggle += ChangeMiniMapPosition;
    20.         }
    21.  
    22.         void OnDisable()
    23.         {
    24.             playerMaster.EventMiniMapToggle -= ChangeMiniMapPosition;
    25.         }
    26.  
    27.         void Update ()
    28.         {
    29.             CheckForMiniMapToggleRequest ();
    30.         }
    31.  
    32.         void SetInitialReferences()
    33.         {
    34.             playerMaster = GetComponent<Player_Master> ();
    35.         }
    36.  
    37.         void CheckForMiniMapToggleRequest()
    38.         {
    39.             if (Input.GetButtonUp(toggleMiniMapButton))
    40.             {
    41.                 ToggleMiniMapState ();
    42.             }
    43.         }
    44.  
    45.         void ToggleMiniMapState()
    46.         {
    47.             if (toggleState == 0)
    48.             {
    49.                 toggleState = 1;
    50.                 playerMaster.CallEventMiniMapToggle ();
    51.             }
    52.             else if (toggleState == 1)
    53.             {
    54.                 toggleState = 2;
    55.                 playerMaster.CallEventMiniMapToggle ();
    56.             }
    57.             else if (toggleState == 2)
    58.             {
    59.                 toggleState = 0;
    60.                 playerMaster.CallEventMiniMapToggle ();
    61.             }
    62.         }
    63.  
    64.         void ChangeMiniMapPosition()
    65.         {
    66.             if (toggleState == 0)
    67.             {
    68.                 miniMapCamera.localPosition = new Vector3 (0, 20, 0);
    69.                 miniMapPanel.enabled = false;
    70.             }
    71.             else if (toggleState == 1)
    72.             {
    73.                 miniMapCamera.localPosition = new Vector3 (0, 20, 0);
    74.                 miniMapPanel.enabled = true;
    75.             }
    76.             else if (toggleState == 2)
    77.             {
    78.                 miniMapCamera.localPosition = new Vector3 (0, 40, 0);
    79.                 miniMapPanel.enabled = true;
    80.             }
    81.         }
    82.     }
    83. }
    Here's one for a mini-map. This one requires some setup. You need to create an image in the player UI, a render texture and a camera. Create the camera as a child of the fps controller, zero its position, and rotate it so it faces straight down. Move it on the Y axis to 20. Plug in your render texture. Scale the image in your UI and put it in a corner or something so its not really in the way. Apply your render texture to a material using an Unlit/texture shader and plug this material into the material slot of your UI image. Pressing the map button will zoom or toggle off the map. Oh yea, its subscribed to a new event in the Player_Master so dont forget to add that event or change those lines of code in ToggleMiniMapState() where the event is called to call the ChangeMiniMapPosition() function.

    Let me know what you guys think.
     
    Last edited: Feb 21, 2017
  7. Saurabh-Saralaya

    Saurabh-Saralaya

    Joined:
    Apr 28, 2016
    Posts:
    23
    Hi there!

    I was testing my project and ,in one of the cases after I killed Max Ranged ally If I picked up his gun, the player would hold 2 of the guns Simultaneously.

    I remember something similar happening with reload and throw, and had fixed it.
    Has this happened to you? and is there any fix for this
     

    Attached Files:

    • 1.PNG
      1.PNG
      File size:
      992.5 KB
      Views:
      921
    • 2.PNG
      2.PNG
      File size:
      1.1 MB
      Views:
      932
  8. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    This only happens when you pickup the weapon of that specific ally? Also is this a bug that you can reproduce at will?

    It sounds like DeactivateAllInventoryItems() (from Player_Inventory) isn't getting called somewhere. Can I look at your Player_Inventory and Item_Pickup scripts?
     
  9. ifan28

    ifan28

    Joined:
    Feb 22, 2017
    Posts:
    1
    Hey GTGD!
    if you can help me make a tutorial player and NPC(enemy) respawn in your GTGD S3 Advanced First Person Shooter tutorial?
    where respawn if player / NPC(enemy) death could spawn into the indicated and respawn limits.
    and Scenario System (Kill all NPC(enemy) game is Winner.
    because me, make a game FPS follow your tutorial GTGD S3 Advanced First Person Shooter.
    Please help. :(
    Thanks. ;)
     
    Last edited: Feb 23, 2017
  10. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Hey @GTGD

    I don't know if you hear this enough, but thank you for taking the time and expending the effort to do this tutorial series. I can't even begin to tell you how much it has helped me to learn c#

    I want to contribute some code I developed. The game I am developing has a lot of items scattered about: pickups of all sorts from enemies, ammo spawns, loot crates, quest items, various destructible objects, etc. In other words I was beginning to grow concerned about the level of instantiate and destroy that was going on, so I decided to just circumvent it altogether and use object pools. I decided to handle this with a new LevelManager Module which I would also use to track objective progress, play level specific audio, and to handle level specific cutscenes and NPC interaction. At this point though it mostly only handles object pools.

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. namespace G5
    7. {
    8.     public class LevelManager_Master : MonoBehaviour
    9.     {
    10.  
    11.         public delegate void LevelManagerEventHandler();
    12.         public event LevelManagerEventHandler EventSpawnObjectPools;
    13.         public event LevelManagerEventHandler EventSpawnItems;
    14.         public event LevelManagerEventHandler EventSpawnAmmo;
    15.         public event LevelManagerEventHandler EventSpawnNPC;
    16.         public event LevelManagerEventHandler EventStopNPCSpawn;
    17.         public event LevelManagerEventHandler EventStartNPCSpawn;
    18.  
    19.  
    20.         public void CallEventSpawnObjectPools()
    21.         {
    22.             if(EventSpawnObjectPools != null)
    23.             {
    24.                 EventSpawnObjectPools ();
    25.             }
    26.         }
    27.  
    28.         public void CallEventSpawnItems()
    29.         {
    30.             if(EventSpawnItems != null)
    31.             {
    32.                 EventSpawnItems ();
    33.             }
    34.         }
    35.  
    36.         public void CallEventSpawnAmmo()
    37.         {
    38.             if(EventSpawnAmmo != null)
    39.             {
    40.                 EventSpawnAmmo ();
    41.             }
    42.         }
    43.  
    44.         public void CallEventSpawnNPC()
    45.         {
    46.             if(EventSpawnNPC != null)
    47.             {
    48.                 EventSpawnNPC ();
    49.             }
    50.         }
    51.  
    52.         public void CallEventStopNPCSpawn()
    53.         {
    54.             if(EventStopNPCSpawn != null)
    55.             {
    56.                 EventStopNPCSpawn ();
    57.             }
    58.         }
    59.  
    60.         public void CallEventStartNPCSpawn()
    61.         {
    62.             if(EventStartNPCSpawn != null)
    63.             {
    64.                 EventStartNPCSpawn();
    65.             }
    66.         }
    67.     }
    68. }
    69.  
    So I started creating a LevelManager prefab by making an empty GameObject and adding this master script. Then:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. namespace G5
    7. {
    8.     public class LevelManager_ObjectPooler : MonoBehaviour
    9.     {
    10.  
    11.         private LevelManager_Master levelMaster;
    12.  
    13.         [System.Serializable]
    14.         public class PooledObjectTypes
    15.         {
    16.             public string pooledObjName;
    17.             public int pooledObjAmount;
    18.             public GameObject pooledObjPrefab;
    19.  
    20.             [HideInInspector]
    21.             public List<GameObject> pooledObjects;
    22.  
    23.             public PooledObjectTypes(string objName, int objAmount, GameObject objPrefab)
    24.             {
    25.                 pooledObjName = objName;
    26.                 pooledObjAmount = objAmount;
    27.                 pooledObjPrefab = objPrefab;
    28.                 pooledObjects = new List<GameObject>();
    29.             }
    30.         }
    31.  
    32.         public List<PooledObjectTypes> objectPools = new List<PooledObjectTypes> ();
    33.  
    34.         void OnEnable()
    35.         {
    36.             SetInitialReferences ();
    37.             levelMaster.EventSpawnObjectPools += CreateObjectPools;
    38.             levelMaster.CallEventSpawnObjectPools ();
    39.         }
    40.  
    41.         void OnDisable()
    42.         {
    43.             levelMaster.EventSpawnObjectPools -= CreateObjectPools;
    44.         }
    45.  
    46.         void SetInitialReferences()
    47.         {
    48.             levelMaster = GetComponent<LevelManager_Master> ();
    49.         }
    50.  
    51.         void CreateObjectPools()
    52.         {
    53.             foreach(PooledObjectTypes pooled in objectPools)
    54.             {
    55.                 for(int i = 0; i < pooled.pooledObjAmount; i++)
    56.                 {
    57.                     GameObject obj = (GameObject)Instantiate (pooled.pooledObjPrefab);
    58.                     obj.SetActive (false);
    59.                     pooled.pooledObjects.Add (obj);
    60.                 }
    61.             }
    62.         }
    63.  
    64.         public GameObject GetObjectFromPool(string oName)
    65.         {
    66.             foreach(PooledObjectTypes pooledTypes in objectPools)
    67.             {
    68.                 for(int i = 0; i < pooledTypes.pooledObjects.Count; i++)
    69.                 {
    70.                     if(pooledTypes.pooledObjName == oName && !pooledTypes.pooledObjects[i].activeInHierarchy && pooledTypes.pooledObjects[i].transform.parent == null)
    71.                     {
    72.                         return pooledTypes.pooledObjects[i];
    73.                     }
    74.                 }
    75.             }
    76.             return null;
    77.         }
    78.     }
    79. }
    80.  
    I added this script which allows the user to define a name, amount, and prefab. This information is used to generate the object pool. At runtime it generates a list of classes each of which contains a list of gameobjects. Passing the name defined earlier in the class to the GetObjectFromPool() function will retrieve the desired object from the pool. Next:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace G5
    6. {
    7.     public class LevelManager_SpawnObjects : MonoBehaviour
    8.     {
    9.  
    10.         private LevelManager_Master levelMaster;
    11.         private LevelManager_ObjectPooler objectPooler;
    12.         public Transform[] objectSpawnPoints;
    13.         public string[] objectsToSpawn;
    14.         public bool waitUntilUnoccupied = true;
    15.         public float rangeCheck = .5f;
    16.         public LayerMask itemLayer;
    17.  
    18.         void OnEnable()
    19.         {
    20.             SetInitialReferences ();
    21.             levelMaster.EventSpawnItems += SpawnObjects;
    22.         }
    23.  
    24.         void OnDisable()
    25.         {
    26.             levelMaster.EventSpawnItems -= SpawnObjects;
    27.         }
    28.  
    29.         void SetInitialReferences()
    30.         {
    31.             levelMaster = GetComponent<LevelManager_Master> ();
    32.             objectPooler = GetComponent<LevelManager_ObjectPooler> ();
    33.         }
    34.  
    35.         void SpawnObjects()
    36.         {
    37.             if(!waitUntilUnoccupied)
    38.             {
    39.                 foreach(Transform spawn in objectSpawnPoints)
    40.                 {
    41.                     string randomObjName = objectsToSpawn[Random.Range(0, objectsToSpawn.Length)];
    42.                     GameObject obj = objectPooler.GetObjectFromPool (randomObjName);
    43.  
    44.                     if (obj != null)
    45.                     {
    46.                         obj.transform.position = spawn.transform.position;
    47.                         obj.transform.rotation = spawn.transform.rotation;
    48.                         obj.SetActive (true);
    49.                     }
    50.                 }
    51.             }
    52.             else if(waitUntilUnoccupied)
    53.             {
    54.                 foreach (Transform spawn in objectSpawnPoints)
    55.                 {
    56.                     if(!IsSpawnOccupied(spawn))
    57.                     {
    58.                         string randomObjName = objectsToSpawn[Random.Range(0, objectsToSpawn.Length)];
    59.                         GameObject obj = objectPooler.GetObjectFromPool (randomObjName);
    60.  
    61.                         if (obj != null)
    62.                         {
    63.                             obj.transform.position = spawn.transform.position;
    64.                             obj.transform.rotation = spawn.transform.rotation;
    65.                             obj.SetActive (true);
    66.                         }
    67.                     }
    68.                 }
    69.             }
    70.         }
    71.  
    72.         bool IsSpawnOccupied(Transform myTransform)
    73.         {
    74.             Collider[] col = Physics.OverlapSphere (myTransform.position, rangeCheck, itemLayer);
    75.  
    76.             if (col.Length == 0)
    77.             {
    78.                 return false;
    79.             }
    80.             else if (col.Length > 0)
    81.             {
    82.                 return true;
    83.             }
    84.             else
    85.             {
    86.                 return false;
    87.             }
    88.         }
    89.     }
    90. }
    91.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace G5
    6. {
    7.     public class LevelManager_SpawnAmmo : MonoBehaviour
    8.     {
    9.  
    10.         private LevelManager_Master levelMaster;
    11.         private LevelManager_ObjectPooler objectPooler;
    12.         public Transform[] ammoSpawnPoints;
    13.         public string[] ammoTypesToSpawn;
    14.         public bool waitUntilUnoccupied = true;
    15.         public float rangeCheck = .5f;
    16.         public LayerMask itemLayer;
    17.  
    18.         void OnEnable()
    19.         {
    20.             SetInitialReferences ();
    21.             levelMaster.EventSpawnAmmo += SpawnAmmo;
    22.         }
    23.  
    24.         void OnDisable()
    25.         {
    26.             levelMaster.EventSpawnAmmo -= SpawnAmmo;
    27.         }
    28.  
    29.         void SetInitialReferences()
    30.         {
    31.             levelMaster = GetComponent<LevelManager_Master> ();
    32.             objectPooler = GetComponent<LevelManager_ObjectPooler> ();
    33.         }
    34.  
    35.         void SpawnAmmo()
    36.         {
    37.             if(!waitUntilUnoccupied)
    38.             {
    39.                 foreach(Transform spawn in ammoSpawnPoints)
    40.                 {
    41.                     string randomAmmoObjName = ammoTypesToSpawn[Random.Range(0, ammoTypesToSpawn.Length)];
    42.                     GameObject obj = objectPooler.GetObjectFromPool (randomAmmoObjName);
    43.  
    44.                     if (obj != null)
    45.                     {
    46.                         obj.transform.position = spawn.transform.position;
    47.                         obj.transform.rotation = spawn.transform.rotation;
    48.                         obj.SetActive (true);
    49.                     }
    50.                 }
    51.             }
    52.             else if(waitUntilUnoccupied)
    53.             {
    54.                 foreach (Transform spawn in ammoSpawnPoints)
    55.                 {
    56.                     if(!IsSpawnOccupied(spawn))
    57.                     {
    58.                         string randomAmmoObjName = ammoTypesToSpawn[Random.Range(0, ammoTypesToSpawn.Length)];
    59.                         GameObject obj = objectPooler.GetObjectFromPool (randomAmmoObjName);
    60.  
    61.                         if (obj != null)
    62.                         {
    63.                             obj.transform.position = spawn.transform.position;
    64.                             obj.transform.rotation = spawn.transform.rotation;
    65.                             obj.SetActive (true);
    66.                         }
    67.                     }
    68.                 }
    69.             }
    70.         }
    71.  
    72.         bool IsSpawnOccupied(Transform myTransform)
    73.         {
    74.             Collider[] col = Physics.OverlapSphere (myTransform.position, rangeCheck, itemLayer);
    75.  
    76.             if (col.Length == 0)
    77.             {
    78.                 return false;
    79.             }
    80.             else if (col.Length > 0)
    81.             {
    82.                 return true;
    83.             }
    84.             else
    85.             {
    86.                 return false;
    87.             }
    88.         }
    89.     }
    90. }
    91.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace G5
    6. {
    7.     public class LevelManager_SpawnNPC : MonoBehaviour
    8.     {
    9.  
    10.         private LevelManager_Master levelMaster;
    11.         private LevelManager_ObjectPooler objectPooler;
    12.         public Transform[] enemySpawnPoints;
    13.         public string[] enemyTypesToSpawn;
    14.         public bool waitUntilUnoccupied = true;
    15.         public float rangeCheck = 2f;
    16.         public LayerMask enemyLayer;
    17.  
    18.         void OnEnable()
    19.         {
    20.             SetInitialReferences ();
    21.             levelMaster.EventSpawnNPC += SpawnNPC;
    22.         }
    23.  
    24.         void OnDisable()
    25.         {
    26.             levelMaster.EventSpawnNPC -= SpawnNPC;
    27.         }
    28.  
    29.         void SetInitialReferences()
    30.         {
    31.             levelMaster = GetComponent<LevelManager_Master> ();
    32.             objectPooler = GetComponent<LevelManager_ObjectPooler> ();
    33.         }
    34.  
    35.         void SpawnNPC()
    36.         {
    37.             if(!waitUntilUnoccupied)
    38.             {
    39.                 foreach(Transform spawn in enemySpawnPoints)
    40.                 {
    41.                     string randomEnemyObjName = enemyTypesToSpawn[Random.Range(0, enemyTypesToSpawn.Length)];
    42.                     GameObject obj = objectPooler.GetObjectFromPool (randomEnemyObjName);
    43.  
    44.                     if (obj != null)
    45.                     {
    46.                         obj.transform.position = spawn.transform.position;
    47.                         obj.transform.rotation = spawn.transform.rotation;
    48.                         obj.SetActive (true);
    49.                     }
    50.                 }
    51.             }
    52.             else if(waitUntilUnoccupied)
    53.             {
    54.                 foreach (Transform spawn in enemySpawnPoints)
    55.                 {
    56.                     if(!IsSpawnOccupied(spawn))
    57.                     {
    58.                         string randomEnemyObjName = enemyTypesToSpawn[Random.Range(0, enemyTypesToSpawn.Length)];
    59.                         GameObject obj = objectPooler.GetObjectFromPool (randomEnemyObjName);
    60.  
    61.                         if (obj != null)
    62.                         {
    63.                             obj.transform.position = spawn.transform.position;
    64.                             obj.transform.rotation = spawn.transform.rotation;
    65.                             obj.SetActive (true);
    66.                         }
    67.                     }
    68.                 }
    69.             }
    70.         }
    71.  
    72.         bool IsSpawnOccupied(Transform myTransform)
    73.         {
    74.             Collider[] col = Physics.OverlapSphere (myTransform.position, rangeCheck, enemyLayer);
    75.  
    76.             if (col.Length == 0)
    77.             {
    78.                 return false;
    79.             }
    80.             else if (col.Length > 0)
    81.             {
    82.                 return true;
    83.             }
    84.             else
    85.             {
    86.                 return false;
    87.             }
    88.         }
    89.     }
    90. }
    91.  
    I begin to split up spawn types by script because I want certain things to spawn at different rates. All three of these scripts work the same but subscribe to different events. The user can define a list of spawn points and a list of names for objects to retrieve from the pool. Each spawn point will perform a spherecast to see if an item or NPC is already present at the location before attempting to spawn a new item or NPC. What is spawned is basically random based on the list of names, but this same formula can be used to make specific scripts for specific items.

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. namespace G5
    7. {
    8.     public class LevelManager_SpawnControl : MonoBehaviour
    9.     {
    10.  
    11.         private LevelManager_Master levelMaster;
    12.         public float objectRespawnRate;
    13.         public bool respawnObjects = true;
    14.         public float ammoRespawnRate;
    15.         public bool respawnAmmo = true;
    16.         public float npcRespawnRate;
    17.         public bool respawnNPC = true;
    18.  
    19.  
    20.         void OnEnable()
    21.         {
    22.             SetInitialReferences ();
    23.             levelMaster.EventStopNPCSpawn += StopNPCSpawn;
    24.             levelMaster.EventStartNPCSpawn += StartNPCSpawn;
    25.         }
    26.  
    27.         void OnDisable()
    28.         {
    29.             levelMaster.EventStopNPCSpawn -= StopNPCSpawn;
    30.             levelMaster.EventStartNPCSpawn -= StartNPCSpawn;
    31.         }
    32.  
    33.         void Start()
    34.         {
    35.             StartCoroutine ("SpawnObjects");
    36.             StartCoroutine ("SpawnAmmo");
    37.             StartCoroutine ("SpawnNPC");
    38.         }
    39.  
    40.         IEnumerator SpawnObjects()
    41.         {
    42.             while(respawnObjects)
    43.             {
    44.                 yield return new WaitForSeconds (objectRespawnRate);
    45.                 levelMaster.CallEventSpawnItems ();
    46.             }
    47.         }
    48.  
    49.         IEnumerator SpawnAmmo()
    50.         {
    51.             while(respawnAmmo)
    52.             {
    53.                 yield return new WaitForSeconds (ammoRespawnRate);
    54.                 levelMaster.CallEventSpawnAmmo ();
    55.             }
    56.         }
    57.  
    58.         IEnumerator SpawnNPC()
    59.         {
    60.             while(respawnNPC)
    61.             {
    62.                 yield return new WaitForSeconds (npcRespawnRate);
    63.                 levelMaster.CallEventSpawnNPC ();
    64.             }
    65.         }
    66.        
    67.         void SetInitialReferences()
    68.         {
    69.             levelMaster = GetComponent<LevelManager_Master> ();
    70.         }
    71.  
    72.         void StartNPCSpawn()
    73.         {
    74.             respawnNPC = true;
    75.             StartCoroutine ("SpawnNPC");
    76.         }
    77.  
    78.         void StopNPCSpawn()
    79.         {
    80.             respawnNPC = false;
    81.             StopCoroutine ("SpawnNPC");
    82.         }
    83.     }
    84. }
    85.  
    Last, we have a script to control the spawn rate of various objects from the object pool, using user defined float values.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. namespace G5
    5. {
    6.     public class Item_Ammo : MonoBehaviour
    7.     {
    8.        
    9.         private Item_Master itemMaster;
    10.         private GameObject playerGo;
    11.         public string ammoName;
    12.         public int quantity;
    13.         public bool isTriggerPickup;
    14.        
    15.         void OnEnable()
    16.         {
    17.             SetInitialReferences();
    18.             itemMaster.EventObjectPickup += TakeAmmo;
    19.         }
    20.  
    21.         void OnDisable()
    22.         {
    23.             itemMaster.EventObjectPickup -= TakeAmmo;
    24.         }
    25.        
    26.         void Start()
    27.         {
    28.             SetInitialReferences();
    29.         }
    30.        
    31.         void SetInitialReferences()
    32.         {
    33.             itemMaster = GetComponent<Item_Master>();
    34.             playerGo = GameManager_References._player;
    35.            
    36.             if(isTriggerPickup)
    37.             {
    38.                 if(GetComponent<Collider>() != null)
    39.                 {
    40.                     GetComponent<Collider>().isTrigger = true;
    41.                 }
    42.                
    43.                 if(GetComponent<Rigidbody>() != null)
    44.                 {
    45.                     GetComponent<Rigidbody>().isKinematic = true;
    46.                 }
    47.             }
    48.         }
    49.        
    50.         void OnTriggerEnter(Collider other)
    51.         {
    52.             if(other.CompareTag(GameManager_References._playerTag) && isTriggerPickup)
    53.             {
    54.                 TakeAmmo();
    55.             }
    56.         }
    57.        
    58.         void TakeAmmo()
    59.         {
    60.             playerGo.GetComponent<Player_Master>().CallEventPickedUpAmmo(ammoName, quantity);
    61.             Deactivate();
    62.         }
    63.  
    64.         void Deactivate()
    65.         {
    66.             if (transform.parent != null)
    67.             {
    68.                 transform.parent = null;
    69.                 gameObject.SetActive (false);
    70.             }
    71.             else
    72.             {
    73.                 gameObject.SetActive (false);
    74.             }
    75.         }
    76.     }
    77. }
    78.  
    79.  
    And here's an example of how to return items to the pool. Simply add theDeactivate function shown at the end of this script and call it instead of Destroy.

    So, that's it so far. Pretty basic, but hopefully it will help to optimize our scenes. I'll add to this as I go along.

    EDIT: Changed the LevelManager_Master and LevelManager_SpawnControl to fix some issues.

    EDIT2: Fixed issues with object pooler activating items in the inventory.
     
    Last edited: Mar 12, 2017
  11. heymencm

    heymencm

    Joined:
    Mar 3, 2017
    Posts:
    1
    Help me pls!
    My NPC_HoldRangeWeapon (scprit) is exacly...but
     
  12. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Hello,

    It sounds like the NPC isn't properly receiving the "ProcessDamage" message. I noticed that you have it written in your code as "ProcessingDamage". Did you also change the function name inside your Enemy_TakeDamage or NPC_TakeDamage script?
     
  13. KyoSaya

    KyoSaya

    Joined:
    May 26, 2016
    Posts:
    4
    Yes that is the problem thank you so much for your help. I forgot about that script it was so long ago.
     
  14. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    No problem, my friend. Happy coding.
     
  15. Adamaxime

    Adamaxime

    Joined:
    Mar 7, 2017
    Posts:
    7
    GTGD your work is really a great one! Thank you.
    All codes work except one, at 86th, video calls "Enemy_NavFlee".
    I get no error but "Enemy" never flee...I do not know what to do. I'm blocked at this video...Thank for helping!
     
  16. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Line 9 should be:
    public string theshardLayer = "Ignore Raycast";

    That error you are getting means that Unity doesn't recognize the layer you are trying to pass it. The layer is usually stored as an integer which is why you use NameToLayer to convert it to one(on line 45). However, since 'Ignore the Raycast' isn't a default layer it doesn't know what you mean, since it can't find that layer (which is why it tells you it needs to be in the range of 0-31).

    If you open up Tags & Layers in the inspector you can see all the layers from 0-31 listed with their corresponding names (if defined). In here you can see that layer 2 is assigned as 'Ignore Raycast'. It's one of unity's standard built-in layers.
     
    Last edited: Mar 7, 2017
  17. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Hello,

    I might be able to help. Could you post your script please?
     
    Adamaxime likes this.
  18. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Hello,

    Does moving the hand targets make any difference? I can't really tell how you have them positioned since you cant see them in play mode, but the first thing I would do is check the rotation values on the handtargets.
     
  19. Adamaxime

    Adamaxime

    Joined:
    Mar 7, 2017
    Posts:
    7
    Hello! here is my script:

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

    namespace S3
    {
    public class Enemy_NavFlee : MonoBehaviour
    {
    public bool isFleeing;
    private Enemy_Master enemyMaster;
    private NavMeshAgent myNavMeshAgent;
    private NavMeshHit navHit;
    private Transform myTransform;
    public Transform fleeTarget;
    private Vector3 runPosition;
    private Vector3 directionToPlayer;
    public float fleeRange = 25;
    private float checkRate;
    private float nextCheck;

    void OnEnable()
    {
    SetInitialReferences();
    enemyMaster.EventEnemyDie += DisableThis;
    enemyMaster.EventEnemySetNavTarget += SetFleeTarget;
    enemyMaster.EventEnemyHealthLow += IShouldFlee;
    enemyMaster.EventEnemyHealthRecovered += IShouldStopFleeing;
    }

    void OnDisable()
    {
    enemyMaster.EventEnemyDie -= DisableThis;
    enemyMaster.EventEnemySetNavTarget -= SetFleeTarget;
    enemyMaster.EventEnemyHealthLow -= IShouldFlee;
    enemyMaster.EventEnemyHealthRecovered -= IShouldStopFleeing;
    }

    void Update()
    {
    if(Time.time > nextCheck)
    {
    nextCheck = Time.time + checkRate;

    CheckIfIShouldFlee();
    }
    }

    void SetInitialReferences()
    {
    enemyMaster = GetComponent<Enemy_Master>();
    myTransform = transform;
    if(GetComponent<NavMeshAgent>() != null)
    {
    myNavMeshAgent = GetComponent<NavMeshAgent>();
    }
    checkRate = Random.Range(0.3f, 0.4f);
    }

    void SetFleeTarget(Transform target)
    {
    fleeTarget = target;
    }

    void IShouldFlee()
    {
    isFleeing = true;

    if(GetComponent<Enemy_NavPursue>() != null)
    {
    GetComponent<Enemy_NavPursue>().enabled = false;
    }
    }

    void IShouldStopFleeing()
    {
    isFleeing = false;

    if (GetComponent<Enemy_NavPursue>() != null)
    {
    GetComponent<Enemy_NavPursue>().enabled = true;
    }
    }

    void CheckIfIShouldFlee()
    {
    if(isFleeing)
    {
    if(fleeTarget != null && !enemyMaster.isOnRoute && !enemyMaster.isNavPaused)
    {
    if(FleeTarget(out runPosition) && Vector3.Distance(myTransform.position, fleeTarget.position) < fleeRange)
    {
    myNavMeshAgent.SetDestination(runPosition);
    enemyMaster.CallEventEnemyWalking();
    enemyMaster.isOnRoute = true;
    }
    }
    }
    }

    bool FleeTarget(out Vector3 result)
    {
    directionToPlayer = myTransform.position - fleeTarget.position;
    Vector3 checkPos = myTransform.position + directionToPlayer;

    if(NavMesh.SamplePosition(checkPos, out navHit, 1.0f, NavMesh.AllAreas))
    {
    result = navHit.position;
    return true;
    }
    else
    {
    result = myTransform.position;
    return false;
    }
    }

    void DisableThis()
    {
    this.enabled = false;
    }
    }
    }
     
  20. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Your script is correct, I think the problem may be that the 'CallEventEnemyHealthLow' event isn't getting fired off in the right place. That event is called from inside Enemy_Health by the 'CheckHealthFraction' function. The problem may be in that script, could i see that one as well?

    BTW, if you use the 'insert' option in the little toolbar in the posting area and choose code you can display your code in a much more readable format.
     
  21. Adamaxime

    Adamaxime

    Joined:
    Mar 7, 2017
    Posts:
    7
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. namespace S3
    6. {
    7.     public class Enemy_Health : MonoBehaviour
    8.     {
    9.  
    10.         private Enemy_Master enemyMaster;
    11.         public int enemyHealth = 100;
    12.         public float healthLow = 25;
    13.  
    14.         void OnEnable()
    15.         {
    16.             SetInitialReferences();
    17.             enemyMaster.EventEnemyDeductHealth += DeductHealth;
    18.             enemyMaster.EventEnemyIncreaseHealth += IncreaseHealth;
    19.         }
    20.          
    21.         void OnDisable()
    22.         {
    23.             enemyMaster.EventEnemyDeductHealth -= DeductHealth;
    24.             enemyMaster.EventEnemyIncreaseHealth -= IncreaseHealth;
    25.         }
    26.  
    27.         //void Update()
    28.         //{
    29.         //    if(Input.GetKeyUp(KeyCode.Period))
    30.         //    {
    31.         //        enemyMaster.CallEventEnemyIncreaseHealth(70);
    32.         //    }
    33.         //}
    34.  
    35.         void SetInitialReferences()
    36.         {
    37.             enemyMaster = GetComponent<Enemy_Master>();
    38.         }
    39.      
    40.         void DeductHealth(int healthChange)
    41.         {
    42.             enemyHealth -= healthChange;
    43.             if(enemyHealth <= 0)
    44.             {
    45.                 enemyHealth = 0;
    46.                 enemyMaster.CallEventEnemyDie();
    47.                 Destroy(gameObject, Random.Range(10, 20));
    48.             }
    49.  
    50.             CheckHealthFraction();
    51.         }
    52.  
    53.         void CheckHealthFraction()
    54.         {
    55.             if(enemyHealth <= healthLow && enemyHealth > 0)
    56.             {
    57.                 enemyMaster.CallEventEnemyHealthLow();
    58.             }
    59.             else if (enemyHealth > healthLow)
    60.             {
    61.                 enemyMaster.CallEventEnemyHealthRecovered();
    62.             }
    63.         }
    64.  
    65.         void IncreaseHealth(int healthChange)
    66.         {
    67.             enemyHealth += healthChange;
    68.             if(enemyHealth > 100)
    69.             {
    70.                 enemyHealth = 100;
    71.             }
    72.  
    73.             CheckHealthFraction();
    74.         }
    75.     }
    76. }
    77.  
    78.  
    Many thanks for your helping!
     
  22. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    This script also matches mine. I think what might be happening is that when 'EventEnemyHealthLow' is run and 'FleeTarget" looks for a navmesh position to run to it cant find one for some reason. You could verify this by adding some log statements to 'FleeTarget'

    Code (CSharp):
    1. bool FleeTarget(out Vector3 result)
    2.         {
    3.             directionToPlayer = myTransform.position - fleeTarget.position;
    4.             Vector3 checkPos = myTransform.position + directionToPlayer;
    5.            
    6.             if(NavMesh.SamplePosition(checkPos, out navHit, 1.0f, NavMesh.AllAreas))
    7.             {
    8.                 result = navHit.position;
    9.                 Debug.Log("Found Flee Target");
    10.                 return true;
    11.             }
    12.             else
    13.             {
    14.                 result = myTransform.position;
    15.                 Debug.Log("Failed to Find a Flee Target");
    16.                 return false;
    17.             }
    18.         }
    That should give you a better idea of what the problem is, at least. If that is what it is though, I have to admit I'm not quite sure how to fix that off the top of my head. Also, the Enemy module will eventually be replaced entirely by the NPC module when you reach chapter 9, so I wouldn't invest to much time trying to iron out the kinks since you're eventually going to replace all that code anyway. Sorry I couldn't help more.
     
  23. Adamaxime

    Adamaxime

    Joined:
    Mar 7, 2017
    Posts:
    7
    Thank you much.
    I'm getting this message:
    "Found Flee Target
    UnityEngine.DebugLog(Object)"
    It means that the code "works", I think..but the problem is that the "enemy does not getting away" and continues to attack..
     
    Last edited: Mar 9, 2017
  24. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Well that's weird. But I think I may know what the problem is.

    Code (CSharp):
    1.         void CheckIfIShouldFlee()
    2.         {
    3.             if(isFleeing)
    4.             {
    5.                 if(fleeTarget != null && !enemyMaster.isOnRoute && !enemyMaster.isNavPaused)
    6.                 {
    7.                     if(FleeTarget(out runPosition) && Vector3.Distance(myTransform.position, fleeTarget.position) < fleeRange)
    8.                     {
    9.                         myNavMeshAgent.SetDestination(runPosition);
    10.                         enemyMaster.CallEventEnemyWalking();
    11.                         enemyMaster.isOnRoute = true;
    12.                     }
    13.                 }
    14.             }
    15.         }
    This part of the Enemy_NavFlee script is responsible for actually assigning the NavAgent's target position to the flee target. It won't work though if the FleeTarget's position is outside of the fleeRange (25 units in this case). How large is your NavMesh? You might want to try increasing the fleeRange in the editor view if you have a large level, since the liklihood of your FleeTarget being out of range would be pretty high. This would explain why the enemy isn't pathing even though it clearly has a target.
     
  25. Adamaxime

    Adamaxime

    Joined:
    Mar 7, 2017
    Posts:
    7
    Yes. Now when touched, the enemy struck and slide towards the player...
    But there is no change even if increasing flee range !
     
    Last edited: Mar 10, 2017
  26. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Ah, I'm sorry. I gave you some bad advice. Sorry, its been a little while since I dealt with the Enemy_Module.

    Code (CSharp):
    1. bool FleeTarget(out Vector3 result)
    2.         {
    3.             directionToPlayer = myTransform.position - fleeTarget.position;
    4.             Vector3 checkPos = myTransform.position + directionToPlayer;
    5.          
    6.             if(NavMesh.SamplePosition(checkPos, out navHit, 3.0f, NavMesh.AllAreas))
    7.             {
    8.                 result = navHit.position;
    9.                 return true;
    10.             }
    11.             else
    12.             {
    13.                 result = myTransform.position;
    14.                 return false;
    15.             }
    16.         }
    On line 109 in Enemy_NavFlee change the third argument from 1.0f to 3.0f and see if that makes any difference. That value controls how far away on the NavMesh that SamplePosition will look for a new position (fleeRange controls how far away from the player it will run before it stops, sorry about that). If 3.0f doesn't work try bumping it up a little more, just be aware the larger the range you set here the more it will impact your performance.

    Also, how close are you to the enemy? I believe with the way the enemy module worked it would still attack you if you were inside its attack range, even if its below the low health threshold. If you haven't already and you were attacking up close, try putting a little distance between you and the enemy after you get their health low, and see if they run.
     
    Last edited: Mar 10, 2017
  27. Adamaxime

    Adamaxime

    Joined:
    Mar 7, 2017
    Posts:
    7
    Thank you again for tying to help me.
    So. I think the code "woks but badly" for me!
    I changed the value you indicate and get this result:.
    - When "fired" the enemy kneels and slides towards me. Sometimes he runs away in this position if i shoot again (when his healt is about 20) -
    (One unique time, he turns back away without kneeling and sliding...!!!!)
     
  28. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    Last edited: Mar 12, 2017
  29. Adamaxime

    Adamaxime

    Joined:
    Mar 7, 2017
    Posts:
    7
    Thank you anyway...:)
     
  30. KyoSaya

    KyoSaya

    Joined:
    May 26, 2016
    Posts:
    4
    Hi, does anybody know what design pattern he is using? I think it was a very good design but I do not know and I want to study more about it.
     
  31. doppie320

    doppie320

    Joined:
    Feb 13, 2017
    Posts:
    7
    This happens heelp me! BTW: I fixed the item pickup script to whom that helped me.

    but good thing i haven't made a new build yet
     
    Last edited: Mar 20, 2017
  32. joewode

    joewode

    Joined:
    Dec 3, 2014
    Posts:
    35
    This looks like a script execution order problem. When you get a null reference error in the console its usually the case. Most of the time it's because of this line:

    playerMaster = GameManager_References._player.GetComponent<Player_Master>();

    A lot of the time using GameManager_References causes this problem. Your Player_Master wasn't getting properly referenced in your Item_Master script, so the event calls weren't firing right. Try this instead:

    playerMaster = GameObject.Find("Player").GetComponent<Player_Master>();

    So far this seems to be a more direct method of finding the player master and hasn't given me any problems with script execution order or null reference errors. Sometimes these things can be fixed by restarting unity as well, just to make things really confusing.

    Anyway, hope that helps.
     
  33. HeizenblogGaming

    HeizenblogGaming

    Joined:
    Jun 12, 2016
    Posts:
    10
    Hi there, love the tutorial series but having a problem with the players Ammo and reloading, for some reason when firing my clip empties out and goes below zero to -1, however it still lets me shoot. I have checked and rechecked the script and even put a Debug.Log in as shown, when I run the game i get to zero and the debug.log pops up but it continues to let me fire indefinately. I'm using Unity version 5.5.0f3

    void CheckAmmoStatus()
    {
    if (currentAmmo <= 0)
    {
    Debug.Log ("Ammo 0");
    currentAmmo = 0;
    gunMaster.isGunLoaded = false;
    }
    else if (currentAmmo > 0)
    {
    gunMaster.isGunLoaded = true;
    }
    }
     
  34. renato736286

    renato736286

    Joined:
    Apr 2, 2017
    Posts:
    1
    Hello guys,

    First time using the forum, but I've already read a lot of things here that helped me with some issues.
    This time I need a help with the wooden hut. The asset is not available anymore in the store.
    I'm looking for another models but I have doubt if in the future I'll probably have problems with the tutorial.
    Can someone help me pointing to some specific model or provide the model itself?

    Thanks.
     
  35. Azure_Zero

    Azure_Zero

    Joined:
    Apr 4, 2013
    Posts:
    1
    Just started video 71 (ragdoll setup)
    And wondering if this is just a Unity version issue
    After the ragdoll is made I have NO Colliders on the bones that were put into the ragdoll, while in the video they did.
    Is there a quick way to get all the colliders on the same bones without needing to manually setup the collider on each bone?
     
  36. Goofy420

    Goofy420

    Joined:
    Apr 27, 2013
    Posts:
    248
    That's either a Unity bug or ragdoll setup was incorrect. You can right click on a GameObject in the scene and click 3D Object>>Ragdoll to open the ragdoll window. It should add Colliders and Rigidbody's and CharacterJoints to the bones.
    Ragdoll wizard requires the character to be of a SkinnedMesh type, also make sure you import it as Humanoid. Select the imported model, in inspector click the Rig tab, and choose the Humanoid dropdown and click apply. If there's a checkmark next to the Configure button, you're good to go, if it's an x then you need to rig the character, you can do this at Mixamo.com and select the auto rig option, upload your static bipedal mesh, and then you can download it rigged as Humanoid.
     
  37. cashleycool

    cashleycool

    Joined:
    May 31, 2017
    Posts:
    2
    Has anybody encountered problems with part 36? The Inventory UI toggle for me isn't enabling and disabling the sphere in which I am using as a test. I have added the GM_ToggleInventoryUI script into the empty GameManager object and filled in the object for the Inventory UI, added the newly added Input key and finally ticked Has Inventory into enable.

    Testing the game, closing the menu and then hitting the inventory key paused the game as intended--except, the inventory from what I can see from the GameManager inspector is enabling or disabling, the GameManager_Master script does tick the 'Is Inventory UI On' on whenever I hit the inventory input key though. Anybody know what the heck is going on?

    I am such a wanker, thought learning Unity for a few months would have warrant little newbie mistakes. What I did mistakenly was:
    void ToggleInventoryUI()
    {
    inventoryUI.SetActive (inventoryUI.activeSelf); and not inventoryUI.SetActive (!inventoryUI.activeSelf);

    Sorry for taking up the space here, you will learn nothing from my mistake, I know I did though.
     
    Last edited: Jun 6, 2017
  38. vladalbescu

    vladalbescu

    Joined:
    Jun 8, 2017
    Posts:
    1


    My attempt at the S3 Chapter 1 challenge. For unknown reasons, it didn't record from the beginning of the game, when there were no evil cubes and all was chill.
     
    GTGD and KUFgoddess like this.
  39. KUFgoddess

    KUFgoddess

    Joined:
    Apr 2, 2015
    Posts:
    27
    Does anyone know how to add health to the player on trigger enter?? My player walks across a box to receive health. I am on chapter 9 and I have been trying to do this for weeks and no luck I feel like im very warm but it just is giving me so much trouble ive tried so many combinations. Like I keep looking at how the enemy script is set up and im trying to do it like but no success.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine.UI;
    4. using UnityEngine.SceneManagement;
    5. using UnityEngine;
    6.  
    7. namespace SpaceHorror
    8. {
    9.     public class Player_Health : MonoBehaviour
    10.     {
    11.         private GameManager_Master gameManagerMaster;
    12.         private Player_Master playerMaster;
    13.         public int playerHealth;
    14.         public string Oddity;
    15.         public Text healthText;
    16.  
    17.  
    18.  
    19.         void OnTriggerEnter(Collider other)
    20.         {
    21.             if (other.CompareTag("Player"))
    22.             {
    23.                 IncreaseHealth();  //<--- this is making it not compile but im not sure if this even makes sense.
    24.  
    25.  
    26.  
    27.             }
    28.  
    29.             SetUI();
    30.         }
    31.                 //void OnTriggerEnter(Collider other)
    32.                 //{
    33.                 //    if (other.CompareTag("Player"))
    34.                 //    {
    35.                 //        playerMaster.CallEventPlayerHealthIncrease = GetComponent<Player_Master>();
    36.  
    37.                 //        Player_Master playerMaster = GetComponent<OtherScript>();
    38.                 //        otherScript.DoSomething();
    39.                 //        //playerMaster.EventPlayerHealthIncrease += IncreaseHealth;
    40.                 //        SetUI();
    41.  
    42.                 //        //playerMaster.GetComponent<Player_Master>().EventPlayerHealthIncrease(increase);
    43.                 //    }
    44.                 //    {
    45.                 //        if (playerHealth > 100)
    46.                 //        {
    47.  
    48.                 //        }
    49.  
    50.  
    51.                 //        //playerMaster.GetComponent<Player_Master>().EventPlayerHealthIncrease(increase);
    52.  
    53.  
    54.                 //    }
    55.                 //}
    56.  
    57.  
    58.                 void OnEnable()
    59.         {
    60.             SetInitialReferences();
    61.             SetUI();
    62.             playerMaster.EventPlayerHealthDeduction += DeductHealth;
    63.             playerMaster.EventPlayerHealthIncrease += IncreaseHealth;
    64.         }
    65.  
    66.         void OnDisable()
    67.         {
    68.             playerMaster.EventPlayerHealthDeduction -= DeductHealth;
    69.             playerMaster.EventPlayerHealthIncrease -= IncreaseHealth;
    70.         }
    71.  
    72.         //void Start()
    73.         //{
    74.         //    StartCoroutine(TestHealthIncrease());
    75.         //}
    76.  
    77.      
    78.         void SetInitialReferences()
    79.         {
    80.             gameManagerMaster = GameObject.Find("GameManager").GetComponent<GameManager_Master>();
    81.             playerMaster = GetComponent<Player_Master>();
    82.         }
    83.  
    84.         //IEnumerator TestHealthIncrease()
    85.         //{
    86.         //    yield return new WaitForSeconds(4);
    87.         //   IncreaseHealth(300);
    88.         //    playerMaster.CallEventPlayerHealthIncrease(1);
    89.         //}
    90.  
    91.         void DeductHealth(int healthChange)
    92.         {
    93.             playerHealth -= healthChange;
    94.             if(playerHealth<=0)
    95.             {
    96.                 playerHealth = 0;
    97.                 gameManagerMaster.CallEventGameOver();
    98.                 SceneManager.LoadScene(Oddity);
    99.  
    100.  
    101.             }
    102.  
    103.             SetUI();
    104.  
    105.         }
    106.  
    107.  
    108.  
    109.  
    110.         void IncreaseHealth(int healthChange)
    111.         {
    112.  
    113.             playerHealth += healthChange;
    114.  
    115.             if(playerHealth>=100)
    116.             {
    117.                 playerHealth = 100;
    118.             }
    119.  
    120.             SetUI();
    121.         }
    122.  
    123.  
    124.  
    125.      
    126.  
    127.  
    128.         void SetUI()
    129.         {
    130.             healthText.text = playerHealth.ToString();
    131.         }
    132.     }
    133. }
     
  40. KUFgoddess

    KUFgoddess

    Joined:
    Apr 2, 2015
    Posts:
    27
    Hey did anyone figure out how to ADD health to the player?
     
  41. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    560
    YouTube will help you with good tutorial.
     
  42. VCGhost

    VCGhost

    Joined:
    Jun 18, 2017
    Posts:
    5
    Error.png
    thank you for you nice teaching style I found your tutorials really nice
    would you please tell me that why is this error appearing I wrote the same script as you wrote in video for menu UI script
     
  43. VCGhost

    VCGhost

    Joined:
    Jun 18, 2017
    Posts:
    5
    and this is the script
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. namespace S3
    5. {
    6.     public class GameManager_ToggleMenu : MonoBehaviour
    7.     {
    8.         private GameManager_Master gameManagerMaster;
    9.         public GameObject menu;
    10.  
    11.  
    12.         // Use this for initialization
    13.         void Start()
    14.         {
    15.             ToggleMenu();
    16.         }
    17.  
    18.         // Update is called once per frame
    19.         void Update()
    20.         {
    21.             CheckForToggleMenuRequest();
    22.         }
    23.         void OnEabled()
    24.         {
    25.             SetInitialRefrences();
    26.             gameManagerMaster.GameOverEvent += ToggleMenu;
    27.         }
    28.  
    29.         void OnDisabled()
    30.         {
    31.             gameManagerMaster.GameOverEvent -= ToggleMenu;
    32.         }
    33.  
    34.         void SetInitialRefrences()
    35.         {
    36.             gameManagerMaster = GetComponent<GameManager_Master>();
    37.         }
    38.  
    39.         void CheckForToggleMenuRequest()
    40.         {
    41.             if (Input.GetKeyUp(KeyCode.Escape) && !gameManagerMaster.isGameOver && !gameManagerMaster.isInventoryUIOn)
    42.             {
    43.                 ToggleMenu();
    44.             }
    45.         }
    46.  
    47.         void ToggleMenu()
    48.         {
    49.             if (menu != null)
    50.             {
    51.                 menu.SetActive(!menu.activeSelf);
    52.                 gameManagerMaster.isMenuOn = !gameManagerMaster.isMenuOn;
    53.                 gameManagerMaster.CallEventMenuToggle();
    54.             }
    55.             else
    56.             {
    57.                 Debug.LogWarning("You Need To Assign a UI Game Object To The Toggle Menu Script In Inspector.");
    58.             }
    59.         }
    60.     }
    61. }
     
  44. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    560
    Put this issue on this section.
    https://forum.unity3d.com/forums/scripting.12/
     
  45. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Look at the name of your OnEnable and OnDisable methods. They are Unity methods and must match the Unity names exactly or else they are never called
     
  46. VCGhost

    VCGhost

    Joined:
    Jun 18, 2017
    Posts:
    5
    really thanks for your help and the attention that you have for answering questions
     
  47. VCGhost

    VCGhost

    Joined:
    Jun 18, 2017
    Posts:
    5
    Hi
    Thank you for your great tutorials
    Would you please tell me how can I solve this error
    It's complaining about Item Ammo script and it's the error
    Error.png
    I really need you help
     
  48. GTGD

    GTGD

    Joined:
    Feb 7, 2012
    Posts:
    436
    Double click on the error to go to the potential problem area in the code. Basically it is saying that the script is trying to get information from an index number in the list that doesn't even exist. For example the list only has two entries but you are trying to access the third entry, but there is no third entry because the list only has two!
     
  49. mattneed

    mattneed

    Joined:
    Jun 25, 2017
    Posts:
    1
    I know this is a really old thread but is there a chance there is an update somewhere for unity 5 so i can do all the lessons?
     
  50. cashleycool

    cashleycool

    Joined:
    May 31, 2017
    Posts:
    2
    Hey guys, this time is regarding the 150th video. I have got no problem with the code in void Patrol() and have manually assigned waypoints; so the enemy is patrolling just fine.

    However, I wanted the enemy to pause in between waypoints for a few seconds whenever it reaches its destination; like how it is seen when allowing enemies to randomly wander (like in bool RandomWanderTarget). I was going to use StartCoroutines, but discovered quickly that it would never work since the NPCState_Patrol script does not utilize MonoBehaviour.

    Whatever should I do? Add another bool then calling it in void Patrol()?

    If anybody has the time to help, that would be really awesome. Sorry for the inconvenience people!