Search Unity

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

Realistic FPS Prefab [RELEASED]

Discussion in 'Assets and Asset Store' started by Deleted User, Apr 5, 2013.

  1. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Hi @Weblox - Try this:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class AI_ToggleActive : MonoBehaviour
    6. {
    7.  
    8.     public AI[] npcs = new AI[0]; // Script variable to hold references to all AI components.
    9.  
    10.     void Start()
    11.     {
    12.         npcs = FindObjectsOfType<AI>(); // Get all AI components on active GameObjects.
    13.     }
    14.  
    15.    public void SetNPCs(bool value)  // Toggle NPCs Active or not
    16.     {
    17.         foreach (var npc in npcs)
    18.         {
    19.             npc.enabled = value;
    20.         }
    21.     }
    22. }
    23.  
    You should be able to select AI_ToggleActive.SetNPCs in your event. It'll have a checkbox that sets all NPCs active (ticked) or inactive (unticked).
     
    Last edited: May 7, 2017
    Weblox likes this.
  2. Weblox

    Weblox

    Joined:
    Apr 11, 2016
    Posts:
    277
    Hi @TonyLi - Thanks again. This made the "SetNPCs" automagically appear in my Unity.Events. :)

    I am not entirely sure I have set the Event correctly, but somehow my Project is having Issues. With the AI_ToggleActive.cs script set in my scene, Unity pauses PlayMode and gives Messages like these :

    NullReferenceException: Object reference not set to an instance of an object
    AI+<AttackTarget>c__Iterator3.MoveNext () (at Assets/RFPSP/Scripts/AI/AI.cs:895)
    UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)

    NullReferenceException: Object reference not set to an instance of an object
    AI+<AttackTarget>c__Iterator3.MoveNext () (at Assets/RFPSP/Scripts/AI/AI.cs:926)
    UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)

    This might be completely unrelated to the script and as far as I could see this (mostly/only) happens to my NPC - Animals that use Melee Attacks with a Legacy setup. Shooter NPCs that use Mecanim don't seem to have an Issue.

    I will do some more bug tracking and upgrade my Project to the latest Version.
    Hopefully it's just one of my NPCs that's not set correctly ;)
     
    Last edited: May 7, 2017
  3. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Try swapping the "npc.enabled = value;" line for these three lines instead:

    Code (csharp):
    1.             npc.StopAllCoroutines();
    2.             npc.spawned = false;
    3.             npc.enabled = value;
    Sorry I don't have time to test this myself.
     
    Weblox likes this.
  4. Weblox

    Weblox

    Joined:
    Apr 11, 2016
    Posts:
    277
    @TonyLi - Thanks a lot! I really appreciate. :)
     
  5. twangydave

    twangydave

    Joined:
    Mar 30, 2017
    Posts:
    41
    Hi there,

    Recent purchaser of RFPS - great asset! I'm using it with Tactical Shooter AI and everything is working really nicely but I have a problem with the bow and arrow. All RFPS weapons are damaging and killing Tactical Shooter AI agents and that includes explosives, all guns, knives and swords. The only weapon I cannot get to damage to the Tactical Shooter AI agents is the bow and arrow. The arrows hit, stick in and can be retrieved but I don't get a hit mark like I do with all the other weapons and no damage is passed. All layers appear OK - any ideas? Cheers!
     
  6. Ghost_Interactive

    Ghost_Interactive

    Joined:
    Jul 8, 2015
    Posts:
    54
    I have a simple Problem @TonyLi !! witch is i want to enable FPS Main, a bit later when the game level starts. For example : a helicopter lands (Animation) then player active !

    my animation is working with scripts : after lands FPS Main get active but gives error (Ironsights, weaponBehavor etc. )!!! if i start the level without animation, works fine.

    ** for activating player i used for helicopter collider enter trigger, simple c# script
     
  7. luniac

    luniac

    Joined:
    Jan 12, 2011
    Posts:
    614
    im interested in buying ur plugin, i hear it's a cleaner plugin compared to UFPS, and im not trying to create a full featured shooter, i just need a nice shooting pistol mechanics,

    How customizable is the movement, i like ur ironsights feel, but i want the overall movement to have DOOM speed, similar to UFPS.
    ur standalone demo has a bit more sluggish movement, this is adjustable?

    Also i use MASTERAUDIO for all my audio. how easy will it be to modify remove audio from ur plugin?

    im also planning to create levels with PROBUILDER, how is integration with that?

    thanks!
     
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    This works for me:

    1. Make sure FPS Main starts inactive. Don't deactivate it during play, even in a Start method.

    2. Deactivate all of the RFPS scripts that assume the scene has an FPS Main, such as WaterZone, MineExplosion, FoliageRustle, AI, etc.

    3. You'll need another camera for your intro cutscene.

    4. At the end of the cutscene, deactivate your cutscene camera and activate FPS Main and all the other scripts (WaterZone, etc.).

    Alternatively, keep FPS Main active all the time. Call MovePlayerAndCamera.ToggleCinemaCamera() before starting your animation. Then call it again after the animation.
     
  9. Deckard_89

    Deckard_89

    Joined:
    Feb 4, 2016
    Posts:
    315
    I just imported RFPS into a fresh project and got this error 8 times:

    Assets/RFPSP/Scripts/AI/AI.cs(508,12): error CS1061: Type `UnityEngine.AI.NavMeshAgent' does not contain a definition for `isStopped' and no extension method `isStopped' of type `UnityEngine.AI.NavMeshAgent' could be found. Are you missing an assembly reference?

    And this once:
    Assets/RFPSP/Scripts/AI/CharacterDamage.cs(261,21): error CS1061: Type `UnityEngine.AI.NavMeshAgent' does not contain a definition for `isStopped' and no extension method `isStopped' of type `UnityEngine.AI.NavMeshAgent' could be found. Are you missing an assembly reference?

    I'm on Unity 5.5.1, which is usually pretty stable.
     
    Last edited: May 16, 2017
  10. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Try redownloading RFPS from inside Unity 5.5.1. Your local cache might have a version for a different version of Unity. Then delete your RFPSP folder and reimport it.
     
  11. Deckard_89

    Deckard_89

    Joined:
    Feb 4, 2016
    Posts:
    315
    @TonyLi No dice : (

    I suppose I'll have to go back to my original idea using UFPS.

    Thanks for trying to help though.
     
  12. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Or use Unity 5.6.0. It might be that the RFPS version uploaded for Unity 5.0 - 5.5.0 doesn't handle a Unity API change introduced in 5.5.1. But Azuline submitted a version specifically for Unity 5.6.0, so that should work.

    UFPS is also great, though, and Opsive provides top-notch support. Both are nice to work with.
     
    Deckard_89 likes this.
  13. petercoleman

    petercoleman

    Joined:
    Feb 21, 2016
    Posts:
    475
    Hi luniac,

    You can adjust various Player and other NPC and or entity speeds movement/animation speeds in their properties boxes...

    Same goes for audio - changeable via entities properties box fields.

    I have been using RFPSP for a few years....and using the free PROBUILDER basic version. I don't use it to design/craft whole levels but use it where it gives me an advantage over the Unity basic primitives. I have not really had a problem with it and RFPSP.

    Peter
     
    luniac likes this.
  14. magique

    magique

    Joined:
    May 2, 2014
    Posts:
    4,030
    I was using Master Audio with RFPS as well and it's doable to replace the built-in audio, but while it's not difficult, it's time consuming. I never fully converted it, but essentially I changed AudioClip properties to just a string for the name of the Master Audio sound id and then in the code where it wants to play an audio clip I just changed that to call into MasterAudio.Play instead. You can also remove the AudioSources from those objects once you are done. Unfortunately, though, if you have to upgrade RFPS at some point then you'd have to do it all over again.
     
    luniac likes this.
  15. Ghost_Interactive

    Ghost_Interactive

    Joined:
    Jul 8, 2015
    Posts:
    54
    Testing Alpha version 0.5 GHOST Fighter, made with RFPS .Many thanks to @TonyLi , he helped me with many scripts..
     
  16. rbm123

    rbm123

    Joined:
    May 24, 2015
    Posts:
    130

    If I install unity 5.4.5 , will I have this error again? which version is the last version which works with RFPS 1.23 ?
     
  17. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    298

    You probably have (on some lines) saying: "return null" and stuff like that.
    So, go into your AI script, and change any of such to: yield return null.
    And so on, check the complete script, for all such places having that,
    ( since - only to have "return null" is not enough anymore ).
    In other words:
    Avoid direct: "return this and that" out of the blue, but always use:
    "yield return this and that"). Try that first, see how it goes.
    Michael.
     
    Last edited: May 20, 2017
  18. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
  19. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    okay, main problems i have right now are:

    My pause menu canvas won't show but unsure why

    MainMenu:
    Code (CSharp):
    1. //MainMenu.cs by Azuline Studios© All Rights Reserved
    2. //displays main menu gui and manages button states
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class MainMenu : MonoBehaviour {
    7.     private FPSPlayer FPSPlayerComponent;
    8. //    private InputControl InputComponent;
    9.     [Tooltip("True if the menu should be activated by pressing the main menu button (default esc key).")]
    10.     public bool useMainMenu = true;
    11.     [Tooltip("True if the menu size should scale with screen size.")]
    12.     public bool scaleWithScreenSize;
    13.     public string levelSelect;
    14.  
    15.     public string titleScreen;
    16.  
    17.     public bool isPaused;
    18.  
    19.     public GameObject pausemenuCanvas;
    20.  
    21.     private bool menuDisplayed;
    22.     private bool resumePress;
    23.  
    24.    
    25.     void Start () {
    26.         //set up menu components and get object references
    27.         FPSPlayerComponent =  Camera.main.GetComponent<CameraControl>().playerObj.GetComponent<FPSPlayer>();
    28. //        InputComponent = FPSPlayerComponent.InputComponent;
    29.        
    30.     }
    31.    
    32.     void Update() {
    33.         //resume game from button press in Update() loop because resuming from OnGUI() causes a lag in smoothing in other scripts
    34.         if(resumePress){
    35.             Time.timeScale = FPSPlayerComponent.menuTime;
    36.             resumePress = false;
    37.             FPSPlayerComponent.paused = false;
    38.             FPSPlayerComponent.menuDisplayed = false;
    39.             this.enabled = false;//deactivate this script to avoid running OnGUI when not needed
    40.         }
    41.     }
    42.  
    43.  
    44.     public void Resume()
    45.     {
    46.         Time.timeScale = FPSPlayerComponent.menuTime;
    47.         resumePress = false;
    48.         FPSPlayerComponent.paused = false;
    49.         FPSPlayerComponent.menuDisplayed = false;
    50.         this.enabled = false;//deactivate this script to avoid running OnGUI when not needed
    51.     }
    52.     public void MapSelector()
    53.     {
    54.         Application.LoadLevel (2);
    55.     }
    56.     public void Restart()
    57.     {
    58.         Application.LoadLevel (Application.loadedLevel);
    59.     }
    60.     public void Options()
    61.     {
    62.  
    63.     }
    64.  
    65.     public void mainMenu()
    66.     {
    67.         Application.LoadLevel (0);
    68.     }
    69.     public void Quit()
    70.     {
    71.         Application.Quit();
    72.         #if UNITY_EDITOR
    73.         UnityEditor.EditorApplication.isPlaying = false;
    74.         #endif
    75.     }
    76.  
    77.            
    78.        
    79. }
    80.  
    81.         //SAVE SYSTEM CODE by Pixel Crushers goes here! https://www.assetstore.unity3d.com/en/#!/content/83057
    82.    
    83.  
    84.  
    FPSPlayer:
    Code (CSharp):
    1. //FPSPlayer.cs by Azuline Studios© All Rights Reserved
    2. //Controls main player actions such as hitpoints and damage, HUD GUIText/Texture element instantiation and update,
    3. //directs player button mappings to other scripts, handles item detection and pickup, and plays basic player sound effects.
    4. using UnityEngine;
    5. using System.Collections;
    6.  
    7. public class FPSPlayer : MonoBehaviour {
    8.     [HideInInspector]
    9.     public Ironsights IronsightsComponent;
    10.     [HideInInspector]
    11.     public InputControl InputComponent;
    12.     [HideInInspector]
    13.     public FPSRigidBodyWalker FPSWalkerComponent;
    14.     [HideInInspector]
    15.     public PlayerWeapons PlayerWeaponsComponent;
    16.     [HideInInspector]
    17.     public WorldRecenter WorldRecenterComponent;
    18.     [HideInInspector]
    19.     public WeaponBehavior WeaponBehaviorComponent;
    20.     [HideInInspector]
    21.     public    SmoothMouseLook MouseLookComponent;
    22.     [HideInInspector]
    23.     public    WeaponEffects WeaponEffectsComponent;
    24.     [HideInInspector]
    25.     public WeaponPivot WeaponPivotComponent;
    26.     [HideInInspector]
    27.     public CameraControl CameraControlComponent;
    28.     [HideInInspector]
    29.     public NPCRegistry NPCRegistryComponent;
    30.     [HideInInspector]
    31.     public GameObject NPCMgrObj;
    32.     private AI AIComponent;
    33.      //other objects accessed by this script
    34.     [HideInInspector]
    35.     public GameObject[] children;//behaviors of these objects are deactivated when restarting the scene
    36.     [HideInInspector]
    37.     public GameObject weaponCameraObj;
    38.     [HideInInspector]
    39.     public GameObject weaponObj;
    40.     [Tooltip("Object reference to the GUITexture object in the project library that renders pain effects on screen.")]
    41.     public GameObject painFadeObj;
    42.     public GameObject levelLoadFadeObj;
    43.     [Tooltip("Object reference to the GUIText object in the project library that renders health amounts on screen.")]
    44.     public GameObject healthGuiObj;
    45.     [HideInInspector]
    46.     public GameObject healthGuiObjInstance;
    47.     [Tooltip("Object reference to the GUIText object in the project library that renders ammo amounts on screen.")]
    48.     public GameObject ammoGuiObj;
    49.     [Tooltip("Object reference to the GUIText object in the project library that renders hunger amounts on screen.")]
    50.     public GameObject hungerGuiObj;
    51.     [HideInInspector]
    52.     public GameObject hungerGuiObjInstance;
    53.     [Tooltip("Object reference to the GUIText object in the project library that renders thirst amounts on screen.")]
    54.     public GameObject thirstGuiObj;
    55.     [HideInInspector]
    56.     public GameObject thirstGuiObjInstance;
    57.     [Tooltip("Object reference to the GUIText object in the project library that renders help text on screen.")]
    58.     public GameObject helpGuiObj;
    59.     [HideInInspector]
    60.     public GameObject helpGuiObjInstance;
    61.     [Tooltip("Object reference to the GUITexture object in the project library that renders crosshair on screen.")]
    62.     public GameObject CrosshairGuiObj;
    63.     [HideInInspector]
    64.     public GameObject CrosshairGuiObjInstance;
    65.     [HideInInspector]
    66.     public GUITexture CrosshairGuiTexture;
    67.     [Tooltip("Object reference to the GUIText object in the project library that renders hitmarker on screen.")]
    68.     public GameObject hitmarkerGuiObj;
    69.     [HideInInspector]
    70.     public GameObject hitmarkerGuiObjInstance;
    71.     [HideInInspector]
    72.     public GUITexture hitmarkerGuiTexture;
    73.  
    74.     private HealthText HealthText;
    75.     private HealthText[] HealthText2;
    76.     private GUIText healthGuiText;
    77.    
    78.     private HungerText HungerText ;
    79.     private HungerText[] HungerText2;
    80.     private GUIText HungerGUIText;
    81.    
    82.     private ThirstText ThirstText;
    83.     private ThirstText[] ThirstText2;
    84.     private GUIText ThirstGUIText;
    85.        
    86.     [HideInInspector]
    87.     public float crosshairWidth;
    88.     private Rect crossRect = new Rect();
    89.     [Tooltip("Size of crosshair relative to screen size.")]
    90.     public float crosshairSize;
    91.     private float oldWidth;
    92.     [HideInInspector]
    93.     public float hitTime = -10.0f;
    94.     [HideInInspector]
    95.     public bool hitMarkerState;
    96.     private Transform mainCamTransform;
    97.     [TooltipAttribute("True if the prefab parent object will be removed on scene load.")]
    98.     public bool removePrefabRoot = true;
    99.    
    100.     //player hit points
    101.     public float hitPoints = 100.0f;
    102.     public float maximumHitPoints = 200.0f;
    103.     [Tooltip("True if player's health should be displayed on the screen.")]
    104.     public bool showHealth = true;
    105.     [Tooltip("True if player's ammo should be displayed on the screen.")]
    106.     public bool showAmmo = true;
    107.     [Tooltip("True if negative hitpoint values should be shown.")]
    108.     public bool showHpUnderZero = true;
    109.     [Tooltip("True if player cannot take damage.")]
    110.     public bool invulnerable;
    111.     [Tooltip("True if the player regenerates their health after health regen delay elapses without player taking damage.")]
    112.     public bool regenerateHealth = false;
    113.     [Tooltip("The maximum amount of hitpoints that should be regenerated.")]
    114.     public float maxRegenHealth = 100.0f;
    115.     [Tooltip("Delay after being damaged that the player should start to regenerate health.")]
    116.     public float healthRegenDelay = 7.0f;
    117.     [Tooltip("Rate at which the player should regenerate health.")]
    118.     public float healthRegenRate = 25.0f;
    119.     private float timeLastDamaged;//time that the player was last damaged
    120.    
    121.     //player hunger
    122.     [Tooltip("True if player should have a hunger attribute that increases over time.")]
    123.     public bool usePlayerHunger;
    124.     [HideInInspector]
    125.     public float maxHungerPoints = 100.0f;//maximum amount that hunger will increase to before players starts to starve
    126.     [TooltipAttribute("Seconds it takes for player to accumulate 1 hunger point.")]
    127.     public float hungerInterval = 7.0f;
    128.     [HideInInspector]
    129.     public float hungerPoints = 0.0f;//total hunger points
    130.     private float lastHungerTime;//time that last hunger point was applied
    131.     private float lastStarveTime;//time that last starve damage was applied
    132.     [TooltipAttribute("Seconds to wait before starve damaging again (should be less than healthRegenDelay to prevent healing of starvation damage).")]
    133.     public float starveInterval = 3.0f;
    134.     [TooltipAttribute("Anount of damage to apply per starve interval.")]
    135.     public float starveDmgAmt = -5.0f;//amount to damage player per starve interval
    136.    
    137.     //player thirst
    138.     [Tooltip("True if player should have a thirst attribute that increases over time.")]
    139.     public bool usePlayerThirst;
    140.     [HideInInspector]
    141.     public float maxThirstPoints = 100.0f;//maximum amount that thirst will increase to before players starts to take thirst damage
    142.     [TooltipAttribute("Seconds it takes for player to accumulate 1 thirst point.")]
    143.     public float thirstInterval = 7.0f;
    144.     [HideInInspector]
    145.     public float thirstPoints = 0.0f;//total thirst points
    146.     private float lastThirstTime;//time that last thirst point was applied
    147.     private float lastThirstDmgTime;//time that last thirst damage was applied
    148.     [TooltipAttribute("Seconds to wait before thirst damaging again (should be less than healthRegenDelay to prevent healing of thirst damage).")]
    149.     public float thirstDmgInterval = 3.0f;
    150.     [Tooltip("Amount to damage player per thirst damage interval.")]
    151.     public float thirstDmgAmt = -5.0f;
    152.  
    153.     [Tooltip("True if player can activate bullet time by pressing button (default T).")]
    154.     public bool allowBulletTime = true;
    155.     [Tooltip("True if help text should be displayed.")]
    156.     public bool showHelpText = true;
    157.    
    158.     //Damage feedback
    159.     private float gotHitTimer = -1.0f;
    160.     private Color PainColor = new Color(0.221f, 0f, 0f, 0.44f);//color of pain screen flash can be selected in editor
    161.     public Texture2D painTexture;
    162.     private Color painFadeColor;//used to modify opacity of pain fade object
    163.     [TooltipAttribute("Amount to kick the player's camera view when damaged.")]
    164.     public float painScreenKickAmt = 0.016f;//magnitude of the screen kicks when player takes damage
    165.    
    166.     //Bullet Time and Pausing
    167.     [TooltipAttribute("Percentage of normal time to use when in bullet time.")]
    168.     [Range(0.0f, 1.0f)]
    169.     public float bulletTimeSpeed = 0.35f;//decrease time to this speed when in bullet time
    170.     [Tooltip("Movement multiplier during bullet time.")]
    171.     public float sloMoMoveSpeed = 2.0f;
    172.     private float pausedTime;//time.timescale value to return to after pausing
    173.     [HideInInspector]
    174.     public bool bulletTimeActive;
    175.     [HideInInspector]
    176.     public float backstabBtTime;
    177.     [HideInInspector]
    178.     public bool backstabBtState;
    179.     private float initialFixedTime;
    180.     [HideInInspector]
    181.     public float usePressTime;
    182.     [HideInInspector]
    183.     public float useReleaseTime;
    184.     private bool useState;
    185.     [HideInInspector]
    186.     public bool pressButtonUpState;
    187.     [HideInInspector]
    188.     public Collider objToPickup;
    189.    
    190.     //zooming
    191.     private bool zoomBtnState = true;
    192.     private float zoomStopTime = 0.0f;//track time that zoom stopped to delay making aim reticle visible again
    193.     [HideInInspector]
    194.     public bool zoomed = false;
    195.     [HideInInspector]
    196.     public float zoomStart = -2.0f;
    197.     [HideInInspector]
    198.     public bool zoomStartState = false;
    199.     [HideInInspector]
    200.     public float zoomEnd = 0.0f;
    201.     [HideInInspector]
    202.     public bool zoomEndState = false;
    203.     private float zoomDelay = 0.4f;
    204.     [HideInInspector]
    205.     public bool dzAiming;
    206.    
    207.     //crosshair
    208.     [Tooltip("Enable or disable the aiming reticle.")]
    209.     public bool crosshairEnabled = true;
    210.     private bool crosshairVisibleState = true;
    211.     private bool crosshairTextureState = false;
    212.     [Tooltip("Set to true to display swap reticle when item under reticle will replace current weapon.")]
    213.     public bool useSwapReticle = true;
    214.     [Tooltip("The texture used for the aiming crosshair.")]
    215.     public Texture2D aimingReticle;
    216.     [Tooltip("The texture used for the hitmarker.")]
    217.     public Texture2D hitmarkerReticle;
    218.     [Tooltip("The texture used for the pick up crosshair.")]
    219.     public Texture2D pickupReticle;
    220.     [Tooltip("The texture used for when the weapon under reticle will replace current weapon.")]
    221.     public Texture2D swapReticle;
    222.     [Tooltip("The texture used for showing that weapon under reticle cannot be picked up.")]
    223.     public Texture2D noPickupReticle;
    224.     [Tooltip("The texture used for the pick up crosshair.")]
    225.     private Texture2D pickupTex;
    226.  
    227.     private Color pickupReticleColor = Color.white;
    228.     [HideInInspector]
    229.     public Color reticleColor = Color.white;
    230.     private Color hitmarkerColor = Color.white;
    231.     [Tooltip("Layers to include for crosshair raycast in hit detection.")]
    232.     public LayerMask rayMask;
    233.     [Tooltip("Distance that player can pickup and activate items.")]
    234.     public float reachDistance = 2.1f;
    235.  
    236.     private RaycastHit hit;
    237.     private RaycastHit hit2;
    238.     private Vector3 camCrosshairPos;
    239.     private Vector3 crosshairPos;
    240.     [HideInInspector]
    241.     public bool raycastCrosshair;
    242.    
    243.     //button and behavior states
    244.     private bool pickUpBtnState = true;
    245.     [HideInInspector]
    246.     public bool restarting = false;//to notify other scripts that level is restarting
    247.    
    248.     //sound effects
    249.     public AudioClip painLittle;
    250.     public AudioClip painBig;
    251.     public AudioClip painDrown;
    252.     public AudioClip gasp;
    253.     public AudioClip catchBreath;
    254.     public AudioClip die;
    255.     public AudioClip dieDrown;
    256.     public AudioClip jumpfx;
    257.     public AudioClip enterBulletTimeFx;
    258.     public AudioClip exitBulletTimeFx;
    259.     public AudioClip hitMarker;
    260.     [Tooltip("Particle effect to play when player blocks attack.")]
    261.     public GameObject blockParticles;
    262.     private ParticleSystem blockParticleSys;
    263.     [Tooltip("Distance from camera to emit blocking particle effect.")]
    264.     public float blockParticlesPos;
    265.  
    266.     private AudioSource[]aSources;//access the audio sources attatched to this object as an array for playing player sound effects
    267.     [HideInInspector]
    268.     public AudioSource otherfx;
    269.     [HideInInspector]
    270.     public AudioSource hitmarkfx;
    271.     private bool bullettimefxstate;
    272.     [HideInInspector]
    273.     public bool blockState;
    274.     [HideInInspector]
    275.     public float blockAngle;
    276.     [HideInInspector]
    277.     public bool canBackstab;//true if player can backstab an unalerted NPC
    278.     private float moveCommandedTime;//last time that following NPCs were commanded to move (for command cooldown)
    279.    
    280.     [HideInInspector]
    281.     public bool menuDisplayed;
    282.     [HideInInspector]
    283.     public float menuTime;
    284.     [HideInInspector]
    285.     public float pauseTime;
    286.     [HideInInspector]
    287.     public bool paused;
    288.     private MainMenu MainMenuComponent;
    289.  
    290.     void Start (){  
    291.  
    292.         if(removePrefabRoot){
    293.             GameObject prefabRoot = transform.parent.transform.gameObject;
    294.             transform.parent.transform.DetachChildren();
    295.             Destroy(prefabRoot);
    296.         }
    297.  
    298.         mainCamTransform = Camera.main.transform;
    299.         //set up external script references
    300.         IronsightsComponent = GetComponent<Ironsights>();
    301.         InputComponent = GetComponent<InputControl>();
    302.         FPSWalkerComponent = GetComponent<FPSRigidBodyWalker>();
    303.         WorldRecenterComponent = GetComponent<WorldRecenter>();
    304.         MouseLookComponent = mainCamTransform.parent.transform.GetComponent<SmoothMouseLook>();
    305.         CameraControlComponent = Camera.main.transform.GetComponent<CameraControl>();
    306.         weaponObj = CameraControlComponent.weaponObj;
    307.         WeaponEffectsComponent = weaponObj.GetComponent<WeaponEffects>();
    308.         PlayerWeaponsComponent = weaponObj.GetComponent<PlayerWeapons>();
    309.         blockParticleSys = blockParticles.GetComponent<ParticleSystem>();
    310.        
    311.         MainMenuComponent = Camera.main.transform.parent.transform.GetComponent<MainMenu>();
    312. //        MainMenuComponent.enabled = false;
    313.         menuDisplayed = false;
    314.        
    315.         NPCMgrObj = GameObject.Find("NPC Manager");
    316.         NPCRegistryComponent = NPCMgrObj.GetComponent<NPCRegistry>();
    317.            
    318.         aSources = GetComponents<AudioSource>();//Initialize audio source
    319.         otherfx = aSources[0] as AudioSource;
    320.         hitmarkfx = aSources[1] as AudioSource;
    321.         otherfx.spatialBlend = 0.0f;
    322.         hitmarkfx.spatialBlend = 0.0f;
    323.        
    324.         //Set time settings
    325.         Time.timeScale = 1.0f;
    326.         initialFixedTime =  Time.fixedDeltaTime;
    327.        
    328.         usePressTime = 0f;
    329.         useReleaseTime = -8f;
    330.        
    331.         //player object collisions
    332.         Physics.IgnoreLayerCollision(11, 12);//no collisions between player object and misc objects like bullet casings
    333.         Physics.IgnoreLayerCollision (12, 12);//no collisions between bullet shells
    334.        
    335.         //weapon object collisions
    336.         Physics.IgnoreLayerCollision(8, 2);//
    337.         Physics.IgnoreLayerCollision(8, 13);//no collisions between weapon and NPCs
    338.         Physics.IgnoreLayerCollision(8, 12);//no collisions between weapon and Objects
    339.         Physics.IgnoreLayerCollision(8, 11);//no collisions between weapon and Player
    340.         Physics.IgnoreLayerCollision(8, 10);//no collisions between weapon and world collision
    341.  
    342.         //Call FadeAndLoadLevel fucntion with fadeIn argument set to true to tell the function to fade in (not fade out and (re)load level)
    343.         GameObject llf = Instantiate(levelLoadFadeObj) as GameObject;
    344.         llf.GetComponent<LevelLoadFade>().FadeAndLoadLevel(Color.black, 2.0f, true);
    345.        
    346.         //create instance of GUIText to display health amount on hud
    347.         healthGuiObjInstance = Instantiate(healthGuiObj,Vector3.zero,transform.rotation) as GameObject;
    348.         if(showHelpText){
    349.             //create instance of GUIText to display help text
    350.             helpGuiObjInstance = Instantiate(helpGuiObj,Vector3.zero,transform.rotation) as GameObject;
    351.         }
    352.         //create instance of GUITexture to display crosshair on hud
    353.         CrosshairGuiObjInstance = Instantiate(CrosshairGuiObj,new Vector3(0.5f,0.5f,0.0f),transform.rotation) as GameObject;
    354.         CrosshairGuiTexture = CrosshairGuiObjInstance.GetComponent<GUITexture>();
    355.         CrosshairGuiTexture.texture = aimingReticle;
    356.         hitmarkerGuiObjInstance = Instantiate(hitmarkerGuiObj,new Vector3(0.5f,0.5f,0.0f),transform.rotation) as GameObject;
    357.         hitmarkerGuiTexture = hitmarkerGuiObjInstance.GetComponent<GUITexture>();
    358.         hitmarkerGuiTexture.texture = hitmarkerReticle;
    359.         hitmarkerGuiTexture.enabled = false;
    360.         //set alpha of hand pickup crosshair
    361.         pickupReticleColor.a = 0.5f;
    362.         //set alpha of aiming reticule and make it 100% transparent if crosshair is disabled
    363.         if(crosshairEnabled){
    364.             reticleColor.a = 0.25f;
    365.             hitmarkerGuiTexture.color = hitmarkerColor;
    366.         }else{
    367.             //make alpha of aiming reticle zero/transparent
    368.             reticleColor.a = 0.0f;
    369.             //set alpha of aiming reticle at start to prevent it from showing, but allow item pickup hand reticle
    370.             CrosshairGuiTexture.color = reticleColor;
    371.             hitmarkerGuiTexture.color = reticleColor;
    372.         }
    373.        
    374.         //set reference for main color element of heath GUIText
    375.         HealthText = healthGuiObjInstance.GetComponent<HealthText>();
    376.         //set reference for shadow background color element of health GUIText
    377.         //this object is a child of the main health GUIText object, so access it as an array
    378.         HealthText2 = healthGuiObjInstance.GetComponentsInChildren<HealthText>();
    379.        
    380.         //initialize health amounts on GUIText objects
    381.         HealthText.healthGui = hitPoints;
    382.         HealthText2[1].healthGui = hitPoints;  
    383.         healthGuiText = HealthText.GetComponent<GUIText>();
    384.        
    385.         if(!showHealth){
    386.             healthGuiObjInstance.gameObject.SetActive(false);
    387.         }
    388.        
    389.         if(usePlayerHunger){
    390.             //create instance of GUIText to display hunger amount on hud
    391.             hungerGuiObjInstance = Instantiate(hungerGuiObj,Vector3.zero,transform.rotation) as GameObject;
    392.             //set reference for main color element of hunger GUIText
    393.             HungerText = hungerGuiObjInstance.GetComponent<HungerText>();
    394.             //set reference for shadow background color element of hunger GUIText
    395.             //this object is a child of the main hunger GUIText object, so access it as an array
    396.             HungerText2 = hungerGuiObjInstance.GetComponentsInChildren<HungerText>();
    397.            
    398.             //initialize hunger amounts on GUIText objects
    399.             HungerText.hungerGui = hungerPoints;
    400.             HungerText2[1].hungerGui = hungerPoints;  
    401.             HungerGUIText = HungerText.GetComponent<GUIText>();
    402.         }
    403.        
    404.         if(usePlayerThirst){
    405.             //create instance of GUIText to display thirst amount on hud
    406.             thirstGuiObjInstance = Instantiate(thirstGuiObj,Vector3.zero,transform.rotation) as GameObject;
    407.             //set reference for main color element of thirst GUIText
    408.             ThirstText = thirstGuiObjInstance.GetComponent<ThirstText>();
    409.             //set reference for shadow background color element of thirst GUIText
    410.             //this object is a child of the main thirst GUIText object, so access it as an array
    411.             ThirstText2 = thirstGuiObjInstance.GetComponentsInChildren<ThirstText>();
    412.            
    413.             //initialize thirst amounts on GUIText objects
    414.             ThirstText.thirstGui = thirstPoints;
    415.             ThirstText2[1].thirstGui = thirstPoints;
    416.             ThirstGUIText = ThirstText.GetComponent<GUIText>();  
    417.         }
    418.        
    419.     }
    420.    
    421.     void LateUpdate () {
    422.    
    423.         if(MouseLookComponent.dzAiming || raycastCrosshair){
    424.             if(!WeaponBehaviorComponent.unarmed
    425.             && Physics.Raycast(mainCamTransform.position, WeaponBehaviorComponent.weaponLookDirection, out hit, 100.0f, rayMask)){
    426.                 camCrosshairPos = Camera.main.WorldToScreenPoint(hit.point);
    427.                 crosshairPos = new Vector3(camCrosshairPos.x / Screen.width, camCrosshairPos.y / Screen.height, 0.0f);
    428.             }else{
    429.                 if(WeaponBehaviorComponent.unarmed){
    430.                     crosshairPos = new Vector3(0.5f, 0.5f, 0.0f);
    431.                 }else{
    432.                     camCrosshairPos = Camera.main.WorldToScreenPoint(WeaponBehaviorComponent.origin + WeaponPivotComponent.childTransform.forward * 2000.0f);
    433.                     crosshairPos = new Vector3(camCrosshairPos.x / Screen.width, camCrosshairPos.y / Screen.height, 0.0f);
    434.                 }
    435.             }
    436.         }else{
    437.             crosshairPos = new Vector3(0.5f, 0.5f, 0.0f);
    438.         }
    439.        
    440.         CrosshairGuiObjInstance.transform.position = Vector3.Lerp(CrosshairGuiObjInstance.transform.position, crosshairPos, (Time.smoothDeltaTime * 20.0f) * 4.0f);  
    441.         hitmarkerGuiObjInstance.transform.position = CrosshairGuiObjInstance.transform.position;  
    442.         hitmarkerColor.a = 0.2f;
    443.         hitmarkerGuiTexture.color = hitmarkerColor;      
    444.        
    445.     }
    446.    
    447.     void Update (){
    448.    
    449.         //detect if menu display button was pressed
    450.         if (InputComponent.menuPress && MainMenuComponent.useMainMenu){
    451.             if(!menuDisplayed){
    452.                 MainMenuComponent.enabled = true;
    453.                 menuDisplayed = true;
    454.             }else{
    455.                 MainMenuComponent.enabled = false;
    456.                 paused = false;
    457.                 menuDisplayed = false;
    458.             }
    459.             if(Time.timeScale > 0.0f || paused){
    460.                 if(!paused){
    461.                     menuTime = Time.timeScale;
    462.                 }
    463.                 Time.timeScale = 0.0f;
    464.             }else{
    465.                 Time.timeScale = menuTime;  
    466.             }
    467.         }
    468.        
    469.         if(InputComponent.pausePress && !menuDisplayed){
    470.             if(Time.timeScale > 0.0f){
    471.                 paused = true;
    472.                 pauseTime = Time.timeScale;
    473.                 Time.timeScale = 0.0f;
    474.             }else{
    475.                 paused = false;
    476.                 Time.timeScale = pauseTime;  
    477.             }
    478.         }
    479.            
    480.         if(allowBulletTime){//make bullet time an optional feature
    481.             if(InputComponent.bulletTimePress){//set bulletTimeActive to true or false based on button input
    482.                 if(!bulletTimeActive){
    483.                     FPSWalkerComponent.moveSpeedMult = Mathf.Clamp(sloMoMoveSpeed, 1f, sloMoMoveSpeed);
    484.                     bulletTimeActive = true;
    485.                 }else{
    486.                     FPSWalkerComponent.moveSpeedMult = 1.0f;
    487.                     bulletTimeActive = false;
    488.                 }
    489.             }
    490.                    
    491.             otherfx.pitch = Time.timeScale;//sync pitch of bullet time sound effects with Time.timescale
    492.             hitmarkfx.pitch = Time.timeScale;
    493.        
    494.             if(Time.timeScale > 0 && !restarting){//decrease or increase Time.timescale when bulletTimeActive is true
    495.                 Time.fixedDeltaTime = initialFixedTime * Time.timeScale;
    496.                 if(bulletTimeActive){
    497.                     if(!bullettimefxstate){
    498.                         otherfx.clip = enterBulletTimeFx;
    499.                         otherfx.PlayOneShot(otherfx.clip, 1.0f);//play enter bullet time sound effect
    500.                         bullettimefxstate = true;
    501.                     }
    502.                     Time.timeScale = Mathf.MoveTowards(Time.timeScale, bulletTimeSpeed, Time.deltaTime * 3.0f);
    503.                 }else{
    504.                     if(bullettimefxstate){
    505.                         otherfx.clip = exitBulletTimeFx;
    506.                         otherfx.PlayOneShot(otherfx.clip, 1.0f);//play exit bullet time sound effect
    507.                         FPSWalkerComponent.moveSpeedMult = 1.0f;
    508.                         bullettimefxstate = false;
    509.                     }
    510.                     if(1.0f - Mathf.Abs(Time.timeScale) > 0.05f){//make sure that timescale returns to exactly 1.0f
    511.                         Time.timeScale = Mathf.MoveTowards(Time.timeScale, 1.0f, Time.deltaTime * 3.0f);
    512.                     }else{
    513.                         Time.timeScale = 1.0f;
    514.                     }
    515.                 }
    516.             }
    517.         }
    518.        
    519.         //set zoom mode to toggle, hold, or both, based on inspector setting
    520.         switch (IronsightsComponent.zoomMode){
    521.             case Ironsights.zoomType.both:
    522.                 zoomDelay = 0.4f;
    523.             break;
    524.             case Ironsights.zoomType.hold:
    525.                 zoomDelay = 0.0f;
    526.             break;
    527.             case Ironsights.zoomType.toggle:
    528.                 zoomDelay = 999.0f;
    529.             break;
    530.         }
    531.        
    532.         //regenerate player health if regenerateHealth var is true
    533.         if(regenerateHealth){
    534.             if(hitPoints < maxRegenHealth && timeLastDamaged + healthRegenDelay < Time.time){
    535.                 HealPlayer(healthRegenRate * Time.deltaTime);  
    536.             }
    537.         }
    538.        
    539.         //apply player hunger if usePlayerHunger var is true
    540.         if(usePlayerHunger){
    541.             thirstGuiObjInstance.SetActive(true);
    542.             //increase player hunger
    543.             if(lastHungerTime + hungerInterval < Time.time){
    544.                 UpdateHunger(1.0f);
    545.             }
    546.             //calculate and apply starvation damage to player
    547.             if(hungerPoints == maxHungerPoints
    548.             && lastStarveTime + starveInterval < Time.time
    549.             && hitPoints > 0.0f){
    550.                 //use a negative heal amount to prevent unneeded damage effects of ApplyDamage function
    551.                 HealPlayer(starveDmgAmt, true);//
    552.                 //fade screen red when taking starvation damage
    553.                 GameObject pf = Instantiate(painFadeObj) as GameObject;//Create instance of painFadeObj
    554.                 pf.GetComponent<PainFade>().FadeIn(PainColor, painTexture, 0.75f);//Call FadeIn function in painFadeObj to fade screen red when damage taken
    555.                 //Call Die function if player's hitpoints have been depleted
    556.                 if (hitPoints < 1.0f){
    557.                     SendMessage("Die");//use SendMessage() to allow other script components on this object to detect player death
    558.                 }
    559.                 //update starvation timers
    560.                 timeLastDamaged = Time.time;
    561.                 lastStarveTime = Time.time;
    562.             }
    563.            
    564.         }else{
    565.             if(thirstGuiObjInstance){
    566.                 thirstGuiObjInstance.SetActive(false);
    567.             }
    568.         }
    569.        
    570.         //apply player thirst if usePlayerThirst var is true
    571.         if(usePlayerThirst){
    572.             hungerGuiObjInstance.SetActive(true);
    573.             //increase player hunger
    574.             if(lastThirstTime + thirstInterval < Time.time){
    575.                 UpdateThirst(1.0f);
    576.             }
    577.             //calculate and apply starvation damage to player
    578.             if(thirstPoints == maxThirstPoints
    579.             && lastThirstDmgTime + thirstDmgInterval < Time.time
    580.             && hitPoints > 0.0f){
    581.                 //use a negative heal amount to prevent unneeded damage effects of ApplyDamage function
    582.                 HealPlayer(thirstDmgAmt, true);
    583.                 //fade screen red when taking starvation damage
    584.                 GameObject pf = Instantiate(painFadeObj) as GameObject;//Create instance of painFadeObj
    585.                 pf.GetComponent<PainFade>().FadeIn(PainColor, painTexture, 0.75f);//Call FadeIn function in painFadeObj to fade screen red when damage taken
    586.                 //Call Die function if player's hitpoints have been depleted
    587.                 if (hitPoints < 1.0f){
    588.                     Die();
    589.                 }
    590.                 //update starvation timers
    591.                 timeLastDamaged = Time.time;
    592.                 lastThirstDmgTime = Time.time;
    593.             }
    594.            
    595.         }else{
    596.             if(hungerGuiObjInstance){
    597.                 hungerGuiObjInstance.SetActive(false);
    598.             }
    599.         }
    600.        
    601.         WeaponBehavior WeaponBehaviorComponent = PlayerWeaponsComponent.CurrentWeaponBehaviorComponent;  
    602.        
    603.         //toggle or hold zooming state by determining if zoom button is pressed or held
    604.         if(InputComponent.zoomHold
    605.         && WeaponBehaviorComponent.canZoom
    606.         && !blockState
    607.         && !IronsightsComponent.reloading
    608.         && !FPSWalkerComponent.proneMove//no zooming while crawling
    609.         && !FPSWalkerComponent.hideWeapon){
    610.             if(!zoomStartState){
    611.                 zoomStart = Time.time;//track time that zoom button was pressed
    612.                 zoomStartState = true;//perform these actions only once
    613.                 zoomEndState = false;
    614.                 if(zoomEnd - zoomStart < zoomDelay * Time.timeScale){//if button is tapped, toggle zoom state
    615.                     if(!zoomed){
    616.                         zoomed = true;
    617.                     }else{
    618.                         zoomed = false;  
    619.                     }
    620.                 }
    621.             }
    622.         }else{
    623.             if(!InputComponent.zoomHold){blockState = false;}//reset block after a hit, so player needs to press block/zoom button again
    624.             if(!zoomEndState){
    625.                 zoomEnd = Time.time;//track time that zoom button was released
    626.                 zoomEndState = true;
    627.                 zoomStartState = false;
    628.                 if(zoomEnd - zoomStart > zoomDelay * Time.timeScale){//if releasing zoom button after holding it down, stop zooming
    629.                     zoomed = false;  
    630.                 }
    631.             }
    632.         }
    633.        
    634.         //cancel zooming while crawling
    635.         if(FPSWalkerComponent.proneMove){
    636.             zoomEndState = true;
    637.             zoomStartState = false;
    638.             zoomed = false;  
    639.         }
    640.        
    641.         //track when player stopped zooming to allow for delay of reticle becoming visible again
    642.         if (zoomed){
    643.             zoomBtnState = false;//only perform this action once per button press
    644.         }else{
    645.             if(!zoomBtnState){
    646.                 zoomStopTime = Time.time;
    647.                 zoomBtnState = true;
    648.             }
    649.         }
    650.        
    651.         //scale crosshair size with screen size by crosshairSize value
    652.         if(oldWidth != Screen.width || crossRect.width != Screen.width * crosshairSize){
    653.             crossRect.width = Screen.width * crosshairSize;
    654.             crossRect.height = Screen.width * crosshairSize;
    655.             crossRect.x = -crossRect.width * 0.5f;
    656.             crossRect.y = -crossRect.height * 0.5f;
    657.             CrosshairGuiTexture.pixelInset = crossRect;
    658.             hitmarkerGuiTexture.pixelInset = crossRect;
    659.             oldWidth = Screen.width;
    660.         }
    661.        
    662.         UpdateHitmarker();
    663.        
    664.         //enable and disable crosshair based on various states like reloading and zooming
    665.         if((IronsightsComponent.reloading || (zoomed && (!dzAiming || WeaponBehaviorComponent.zoomIsBlock) && !WeaponBehaviorComponent.showZoomedCrosshair))
    666.         && !CameraControlComponent.thirdPersonActive){
    667.             //don't disable reticle if player is using a melee weapon or if player is unarmed
    668.             if((WeaponBehaviorComponent.meleeSwingDelay == 0 || WeaponBehaviorComponent.zoomIsBlock) && !WeaponBehaviorComponent.unarmed){
    669.                 if(crosshairVisibleState){
    670.                     //disable the GUITexture element of the instantiated crosshair object
    671.                     //and set state so this action will only happen once.
    672.                     CrosshairGuiTexture.enabled = false;
    673.                     crosshairVisibleState = false;
    674.                 }
    675.             }
    676.         }else{
    677.             //Because of the method that is used for non magazine reloads, an additional check is needed here
    678.             //to make the reticle appear after the last bullet reload time has elapsed. Proceed with no check
    679.             //for magazine reloads.
    680.             if((WeaponBehaviorComponent.bulletsPerClip != WeaponBehaviorComponent.bulletsToReload
    681.                 && WeaponBehaviorComponent.reloadLastStartTime + WeaponBehaviorComponent.reloadLastTime < Time.time)
    682.             || WeaponBehaviorComponent.bulletsPerClip == WeaponBehaviorComponent.bulletsToReload){
    683.                 //allow a delay before enabling crosshair again to let the gun return to neutral position
    684.                 //by checking the zoomStopTime value
    685.                 if(zoomStopTime + 0.2f < Time.time){
    686.                     if(!crosshairVisibleState){
    687.                         CrosshairGuiTexture.enabled = true;
    688.                         crosshairVisibleState = true;
    689.                     }
    690.                 }
    691.             }
    692.         }
    693.        
    694.         if(crosshairEnabled){
    695.             if(WeaponBehaviorComponent.showAimingCrosshair){
    696.                 if(!WeaponPivotComponent.deadzoneZooming){
    697.                     if(!WeaponPivotComponent.deadzoneLooking){
    698.                         reticleColor.a = 0.25f;
    699.                     }else{
    700.                         reticleColor.a = 0.5f;
    701.                     }
    702.                 }else{
    703.                     if(!CameraControlComponent.thirdPersonActive){
    704.                         if(zoomed){
    705.                             reticleColor.a = 0.5f;
    706.                         }else{
    707.                             if(WeaponPivotComponent.swayLeadingMode){
    708.                                 reticleColor.a = 0.25f;
    709.                             }else{
    710.                                 reticleColor.a = 0.0f;//no crosshair for goldeneye/perfect dark style, non-zoomed aiming
    711.                             }
    712.                         }
    713.                     }else{
    714.                         reticleColor.a = 0.25f;
    715.                     }
    716.                 }
    717.                 CrosshairGuiTexture.color = reticleColor;
    718.             }else{
    719.                 //make alpha of aiming reticle zero/transparent
    720.                 reticleColor.a = 0.0f;
    721.                 //set alpha of aiming reticle at start to prevent it from showing, but allow item pickup hand reticle
    722.                 CrosshairGuiTexture.color = reticleColor;
    723.             }
    724.         }else{
    725.             reticleColor.a = 0.0f;
    726.             CrosshairGuiTexture.color = reticleColor;
    727.         }
    728.                
    729.         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    730.         //Pick up or activate items  
    731.         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    732.        
    733.         if(InputComponent.useHold){
    734.             if(!useState){
    735.                 usePressTime = Time.time;
    736.                 objToPickup = hit.collider;
    737.                 useState = true;
    738.             }
    739.         }else{
    740.             if(useState){
    741.                 useReleaseTime = Time.time;
    742.                 useState = false;
    743.             }
    744.             pressButtonUpState = false;
    745.         }
    746.            
    747.         if(!IronsightsComponent.reloading//no item pickup when reloading
    748.         && !WeaponBehaviorComponent.lastReload//no item pickup when when reloading last round in non magazine reload
    749.         && !PlayerWeaponsComponent.switching//no item pickup when switching weapons
    750.         && !FPSWalkerComponent.holdingObject//don't pick up objects if player is dragging them
    751.         && (!FPSWalkerComponent.canRun || FPSWalkerComponent.inputY == 0)//no item pickup when sprinting
    752.             //there is a small delay between the end of canRun and the start of sprintSwitching (in PlayerWeapons script),
    753.             //so track actual time that sprinting stopped to avoid the small time gap where the pickup hand shows briefly
    754.         && ((FPSWalkerComponent.sprintStopTime + 0.4f) < Time.time)){
    755.             //raycast a line from the main camera's origin using a point extended forward from camera position/origin as a target to get the direction of the raycast
    756.             //and scale the distance of the raycast based on the playerHeightMod value in the FPSRigidbodyWalker script
    757.             if((!CameraControlComponent.thirdPersonActive && Physics.Raycast(mainCamTransform.position,
    758.                                                    WeaponBehaviorComponent.weaponLookDirection,
    759.                                                    out hit,
    760.                                                    reachDistance + FPSWalkerComponent.playerHeightMod,
    761.                                                    rayMask))
    762.             //thirdperson item detection for use button and crosshair
    763.             ||(CameraControlComponent.thirdPersonActive && Physics.Raycast(mainCamTransform.position + mainCamTransform.forward * (CameraControlComponent.zoomDistance + CameraControlComponent.currentDistance + 0.5f),
    764.                                                  mainCamTransform.forward, out hit,
    765.                                                  reachDistance + FPSWalkerComponent.playerHeightMod,
    766.                                                  rayMask))
    767.             ){
    768.                
    769.                 //Detect if player can backstab NPCs
    770.                 if(WeaponBehaviorComponent.meleeSwingDelay > 0 && hit.collider.gameObject.layer == 13){
    771.                     if(hit.collider.gameObject.GetComponent<AI>() || hit.collider.gameObject.GetComponent<LocationDamage>()){
    772.                         if(hit.collider.gameObject.GetComponent<AI>()){
    773.                             AIComponent = hit.collider.gameObject.GetComponent<AI>();
    774.                         }else{
    775.                             AIComponent = hit.collider.gameObject.GetComponent<LocationDamage>().AIComponent;
    776.                         }
    777.                         if(AIComponent.playerIsBehind && AIComponent.CharacterDamageComponent.hitPoints > 0){
    778.                             canBackstab = true;
    779.                         }else{
    780.                             canBackstab = false;
    781.                         }
    782.                     }else{
    783.                         canBackstab = false;
    784.                     }
    785.                 }else{
    786.                     canBackstab = false;
    787.                 }
    788.                
    789.                 if(hit.collider.gameObject.tag == "Usable"){//if the object hit by the raycast is a pickup item and has the "Usable" tag
    790.                    
    791.                     if (pickUpBtnState && usePressTime - useReleaseTime < 0.4f && usePressTime + 0.4f > Time.time && objToPickup == hit.collider){
    792.                         //run the PickUpItem function in the pickup object's script
    793.                         hit.collider.SendMessageUpwards("PickUpItem", transform.gameObject, SendMessageOptions.DontRequireReceiver);
    794.                         //run the ActivateObject function of this object's script if it has the "Usable" tag
    795.                         hit.collider.SendMessageUpwards("ActivateObject", SendMessageOptions.DontRequireReceiver);
    796.                         pickUpBtnState = false;
    797.                         FPSWalkerComponent.cancelSprint = true;
    798.                         usePressTime = -8f;
    799.                         objToPickup = null;
    800.                     }
    801.                    
    802.                     //determine if pickup item is using a custom pickup reticle and if so set pickupTex to custom reticle
    803.                     if(pickUpBtnState){//check pickUpBtnState to prevent reticle from briefly showing custom/general pickup icon briefly when picking up last weapon before maxWeapons are obtained
    804.                        
    805.                         //determine if item under reticle is a weapon pickup
    806.                         if(hit.collider.gameObject.GetComponent<WeaponPickup>()){
    807.                             //set up external script references
    808.                             WeaponBehavior PickupWeaponBehaviorComponent = PlayerWeaponsComponent.weaponOrder[hit.collider.gameObject.GetComponent<WeaponPickup>().weaponNumber].GetComponent<WeaponBehavior>();
    809.                             WeaponPickup WeaponPickupComponent = hit.collider.gameObject.GetComponent<WeaponPickup>();
    810.                            
    811.                             if(PlayerWeaponsComponent.totalWeapons == PlayerWeaponsComponent.maxWeapons//player has maximum weapons
    812.                             && PickupWeaponBehaviorComponent.addsToTotalWeaps){//weapon adds to total inventory
    813.                                
    814.                                 //player does not have weapon under reticle
    815.                                 if(!PickupWeaponBehaviorComponent.haveWeapon
    816.                                 //and weapon under reticle hasn't been picked up from an item with removeOnUse set to false
    817.                                 && !PickupWeaponBehaviorComponent.dropWillDupe){  
    818.                                    
    819.                                     if(!useSwapReticle){//if useSwapReticle is true, display swap reticle when item under reticle will replace current weapon
    820.                                         if(WeaponPickupComponent.weaponPickupReticle){
    821.                                             //display custom weapon pickup reticle if the weapon item has one defined
    822.                                             pickupTex = WeaponPickupComponent.weaponPickupReticle;  
    823.                                         }else{
    824.                                             //weapon has no custom pickup reticle, just show general pickup reticle
    825.                                             pickupTex = pickupReticle;
    826.                                         }
    827.                                     }else{
    828.                                         //display weapon swap reticle if player has max weapons and can swap held weapon for pickup under reticle
    829.                                         pickupTex = swapReticle;
    830.                                     }
    831.                                    
    832.                                 }else{
    833.                                    
    834.                                     //weapon under reticle is not removed on use and is in player's inventory, so show cantPickup reticle
    835.                                     if(!WeaponPickupComponent.removeOnUse){
    836.                                        
    837.                                         pickupTex = noPickupReticle;
    838.                                        
    839.                                     }else{//weapon is removed on use, so show standard or custom pickup reticle
    840.                                        
    841.                                         if(WeaponPickupComponent.weaponPickupReticle){
    842.                                             //display custom weapon pickup reticle if the weapon item has one defined
    843.                                             pickupTex = WeaponPickupComponent.weaponPickupReticle;  
    844.                                         }else{
    845.                                             //weapon has no custom pickup reticle, just show general pickup reticle
    846.                                             pickupTex = pickupReticle;
    847.                                         }
    848.                                        
    849.                                     }
    850.                                    
    851.                                 }
    852.                             }else{//total weapons not at maximum and weapon under reticle does not add to inventory
    853.                                
    854.                                 if(!PickupWeaponBehaviorComponent.haveWeapon
    855.                                 && !PickupWeaponBehaviorComponent.dropWillDupe
    856.                                 || WeaponPickupComponent.removeOnUse){
    857.                                    
    858.                                     if(WeaponPickupComponent.weaponPickupReticle){
    859.                                         //display custom weapon pickup reticle if the weapon item has one defined
    860.                                         pickupTex = WeaponPickupComponent.weaponPickupReticle;  
    861.                                     }else{
    862.                                         //weapon has no custom pickup reticle, just show general pickup reticle
    863.                                         pickupTex = pickupReticle;
    864.                                     }
    865.                                    
    866.                                 }else{
    867.                                     pickupTex = noPickupReticle;
    868.                                 }
    869.                                
    870.                             }
    871.                         //determine if item under reticle is a health pickup  
    872.                         }else if(hit.collider.gameObject.GetComponent<HealthPickup>()){
    873.                             //set up external script references
    874.                             HealthPickup HealthPickupComponent = hit.collider.gameObject.GetComponent<HealthPickup>();
    875.                            
    876.                             if(HealthPickupComponent.healthPickupReticle){
    877.                                 pickupTex = HealthPickupComponent.healthPickupReticle;  
    878.                             }else{
    879.                                 pickupTex = pickupReticle;
    880.                             }
    881.                         //determine if item under reticle is an ammo pickup
    882.                         }else if(hit.collider.gameObject.GetComponent<AmmoPickup>()){
    883.                             //set up external script references
    884.                             AmmoPickup AmmoPickupComponent = hit.collider.gameObject.GetComponent<AmmoPickup>();
    885.                            
    886.                             if(AmmoPickupComponent.ammoPickupReticle){
    887.                                 pickupTex = AmmoPickupComponent.ammoPickupReticle;  
    888.                             }else{
    889.                                 pickupTex = pickupReticle;
    890.                             }
    891.                         }else{
    892.                             pickupTex = pickupReticle;
    893.                         }
    894.                     }
    895.                    
    896.                     UpdateReticle(false);//show pickupReticle if raycast hits a pickup item
    897.  
    898.                 }else{
    899.                     objToPickup = null;//cancel use press if player moves away
    900.                     if(hit.collider.gameObject.layer == 13){//switch to pickup reticle if this NPC can be interacted with
    901.                         if(hit.collider.gameObject.GetComponent<AI>()
    902.                         || hit.collider.gameObject.GetComponent<LocationDamage>()){
    903.                             if(hit.collider.gameObject.GetComponent<AI>()){
    904.                                 AIComponent = hit.collider.gameObject.GetComponent<AI>();
    905.                             }else{
    906.                                 AIComponent = hit.collider.gameObject.GetComponent<LocationDamage>().AIComponent;
    907.                             }
    908.                             if(AIComponent.factionNum == 1 && AIComponent.followOnUse && AIComponent.enabled){
    909.                                 pickupTex = pickupReticle;
    910.                                 UpdateReticle(false);
    911.                                 if (pickUpBtnState && InputComponent.useHold){
    912.                                     AIComponent.CommandNPC();//command NPC to follow or stay put
    913.                                     pickUpBtnState = false;
    914.                                     FPSWalkerComponent.cancelSprint = true;
    915.                                 }
    916.                             }else{
    917.                                 UpdateReticle(true);//show aiming reticle crosshair if item is not a pickup item
    918.                             }
    919.                         }else{
    920.                             if(crosshairTextureState){
    921.                                 UpdateReticle(true);//show aiming reticle crosshair if item is not a pickup item
    922.                             }
    923.                         }
    924.                     }else{
    925.                         if(crosshairTextureState){
    926.                             UpdateReticle(true);//show aiming reticle crosshair if item is not a pickup item
    927.                         }
    928.                     }
    929.                 }
    930.             }else{
    931.                 canBackstab = false;
    932.                 if(crosshairTextureState){
    933.                     UpdateReticle(true);//show aiming reticle crosshair if raycast hits nothing
    934.                 }
    935.                 //Command NPCs to move to location under crosshair
    936.                 if(moveCommandedTime + 0.5f < Time.time &&
    937.                 ((!CameraControlComponent.thirdPersonActive && Physics.Raycast(mainCamTransform.position, WeaponBehaviorComponent.weaponLookDirection, out hit2, 500f, rayMask))
    938.                 ||(CameraControlComponent.thirdPersonActive && Physics.Raycast(mainCamTransform.position, mainCamTransform.forward, out hit2, 500f, rayMask)))){
    939.                     if(hit2.collider.gameObject.layer == 0){
    940.                         if (pickUpBtnState && InputComponent.useHold){
    941.                             NPCRegistryComponent.MoveFolowingNpcs(hit2.point);
    942.                             moveCommandedTime = Time.time;
    943.                             pickUpBtnState = false;
    944.                         }
    945.                     }
    946.                 }
    947.             }
    948.         }else{
    949.             canBackstab = false;
    950.             if(crosshairTextureState){
    951.                 UpdateReticle(true);//show aiming reticle crosshair if reloading, switching weapons, or sprinting
    952.             }
    953.         }
    954.        
    955.         //only register one press of E key to make player have to press button again to pickup items instead of holding E
    956.         if (InputComponent.useHold){
    957.             pickUpBtnState = false;
    958.         }else{
    959.             pickUpBtnState = true;  
    960.         }
    961.    
    962.     }
    963.    
    964. //    void OnDrawGizmos() {
    965.         //draw red dot at crosshair raycast position
    966. //        Gizmos.color = Color.red;
    967. //        Gizmos.DrawSphere(hit2.point, 0.2f);
    968. //    }
    969.    
    970.     //set reticle type based on the boolean value passed to this function
    971.     public void UpdateReticle( bool reticleType ){
    972.         if(!reticleType){
    973.             CrosshairGuiTexture.texture = pickupTex;
    974.             CrosshairGuiTexture.color = pickupReticleColor;
    975.             crosshairTextureState = true;
    976.         }else{
    977.             CrosshairGuiTexture.texture = aimingReticle;
    978.             CrosshairGuiTexture.color = reticleColor;
    979.             crosshairTextureState = false;  
    980.         }
    981.     }
    982.    
    983.     void UpdateHitmarker(){
    984.         if(hitTime + 0.3f > Time.time){
    985.             if(!hitMarkerState){
    986.                 if(WeaponBehaviorComponent.meleeSwingDelay == 0 && !WeaponBehaviorComponent.meleeActive){
    987.                     hitmarkerGuiTexture.enabled = true;
    988.                     hitmarkfx.clip = hitMarker;
    989.                     hitmarkfx.PlayOneShot(hitmarkfx.clip, 1.0f);
    990.                     hitMarkerState = true;
    991.                 }
    992.             }
    993.         }else{
    994.             if(hitMarkerState){
    995.                 hitMarkerState = false;
    996.             }
    997.             hitmarkerGuiTexture.enabled = false;
    998.         }
    999.     }
    1000.    
    1001.     public void UpdateHitTime(){
    1002.         hitTime = Time.time;//used for hitmarker
    1003.         hitMarkerState = false;  
    1004.     }
    1005.    
    1006.     //Activate bullet time for a specific duration
    1007.     public IEnumerator ActivateBulletTime (float duration){
    1008.         if(!bulletTimeActive){
    1009.             bulletTimeActive = true;
    1010.         }else{
    1011.             yield break;
    1012.         }
    1013.         float startTime = Time.time;
    1014.         while(true){
    1015.             if(startTime + duration < Time.time){
    1016.                 bulletTimeActive = false;
    1017.                 yield break;
    1018.             }
    1019.             yield return new WaitForSeconds(0.1f);
    1020.         }  
    1021.     }
    1022.    
    1023.     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1024.     //Update player attributes
    1025.     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1026.    
    1027.     //add hitpoints to player health
    1028.     public void HealPlayer( float healAmt, bool isHungryThirsty = false ){
    1029.            
    1030.         if (hitPoints < 1.0f){//Don't add health if player is dead
    1031.             return;
    1032.         }
    1033.        
    1034.         //Apply healing
    1035.         if(hitPoints + healAmt > maximumHitPoints){
    1036.             hitPoints = maximumHitPoints;
    1037.         }else{
    1038.             //Call Die function if player's hitpoints have been depleted
    1039.             if(healAmt < 0){
    1040.                 if(!isHungryThirsty){
    1041.                     ApplyDamage(healAmt);//allow items that cause damage when consumed
    1042.                 }else{
    1043.                     hitPoints += healAmt;//waste away from hunger or thirst
    1044.                 }
    1045.             }else{
    1046.                 hitPoints += healAmt;
    1047.             }
    1048.         }
    1049.            
    1050.         //set health hud value to hitpoints remaining
    1051.         HealthText.healthGui = Mathf.Round(hitPoints);
    1052.         HealthText2[1].healthGui = Mathf.Round(hitPoints);
    1053.            
    1054.         //change color of hud health element based on hitpoints remaining
    1055.         if (hitPoints <= 25.0f){
    1056.             healthGuiText.material.color = Color.red;
    1057.         }else if (hitPoints <= 40.0f){
    1058.             healthGuiText.material.color = Color.yellow;  
    1059.         }else{
    1060.             healthGuiText.material.color = HealthText.textColor;  
    1061.         }
    1062.  
    1063.     }
    1064.    
    1065.     //update the hunger amount for the player
    1066.     public void UpdateHunger( float hungerAmt ){
    1067.        
    1068.         if (hitPoints < 1.0f){//Don't add hunger if player is dead
    1069.             return;
    1070.         }
    1071.        
    1072.         //Apply hungerAmt
    1073.         if(hungerPoints + hungerAmt > maxHungerPoints){
    1074.             hungerPoints = maxHungerPoints;
    1075.         }else{
    1076.             hungerPoints += hungerAmt;
    1077.         }
    1078.        
    1079.         hungerPoints = Mathf.Clamp(hungerPoints, 0.0f, hungerPoints);
    1080.            
    1081.         //set hunger hud value to hunger points remaining
    1082.         HungerText.hungerGui = Mathf.Round(hungerPoints);
    1083.         HungerText2[1].hungerGui = Mathf.Round(hungerPoints);
    1084.            
    1085.         //change color of hud hunger element based on hunger points
    1086.         if (hungerPoints <= 65.0f){
    1087.             HungerGUIText.material.color = HungerText.textColor;
    1088.         }else if (hungerPoints <= 85.0f){
    1089.                 HungerGUIText.material.color = Color.yellow;  
    1090.         }else{
    1091.             HungerGUIText.material.color = Color.red;  
    1092.         }
    1093.        
    1094.         lastHungerTime = Time.time;  
    1095.     }
    1096.    
    1097.     //update the thirst amount for the player
    1098.     public void UpdateThirst( float thirstAmt ){
    1099.        
    1100.         if (hitPoints < 1.0f){//Don't add thirst if player is dead
    1101.             return;
    1102.         }
    1103.        
    1104.         //Apply thirstAmt
    1105.         if(thirstPoints + thirstAmt > maxThirstPoints){
    1106.             thirstPoints = maxThirstPoints;
    1107.         }else{
    1108.             thirstPoints += thirstAmt;
    1109.         }
    1110.        
    1111.         thirstPoints = Mathf.Clamp(thirstPoints, 0.0f, thirstPoints);
    1112.            
    1113.         //set thirst hud value to thirst points remaining
    1114.         ThirstText.thirstGui = Mathf.Round(thirstPoints);
    1115.         ThirstText2[1].thirstGui = Mathf.Round(thirstPoints);
    1116.            
    1117.         //change color of hud thirst element based on thirst points
    1118.         if (thirstPoints <= 65.0f){
    1119.             ThirstGUIText.material.color = ThirstText.textColor;
    1120.         }else if (thirstPoints <= 85.0f){
    1121.                 ThirstGUIText.material.color = Color.yellow;  
    1122.         }else{
    1123.             ThirstGUIText.material.color = Color.red;  
    1124.         }
    1125.        
    1126.         lastThirstTime = Time.time;
    1127.     }
    1128.    
    1129.     //remove hitpoints from player health
    1130.     public void ApplyDamage ( float damage, Transform attacker = null, bool isMeleeAttack = false ){
    1131.  
    1132.         float appliedPainKickAmt;
    1133.            
    1134.         if (hitPoints < 1.0f){//Don't apply damage if player is dead
    1135.             if(!showHpUnderZero){hitPoints = 0.0f;}
    1136.             return;
    1137.         }
    1138.        
    1139.         //detect if attacker is inside player block zone
    1140.         if(attacker != null
    1141.         && WeaponBehaviorComponent.zoomIsBlock
    1142.         && WeaponBehaviorComponent.blockDefenseAmt > 0f
    1143.         && zoomed
    1144.         && ((WeaponBehaviorComponent.onlyBlockMelee && isMeleeAttack) || !WeaponBehaviorComponent.onlyBlockMelee)
    1145.         && WeaponBehaviorComponent.shootStartTime + WeaponBehaviorComponent.fireRate < Time.time){
    1146.        
    1147.             Vector3 toTarget = (attacker.position - transform.position).normalized;
    1148.             blockAngle = Vector3.Dot(toTarget, transform.forward);
    1149.            
    1150.             if(Vector3.Dot(toTarget, transform.forward) > WeaponBehaviorComponent.blockCoverage){
    1151.            
    1152.                 damage *= 1f - WeaponBehaviorComponent.blockDefenseAmt;
    1153.                 otherfx.clip = WeaponBehaviorComponent.blockSound;
    1154.                 otherfx.PlayOneShot(otherfx.clip, 1.0f);
    1155.                
    1156.                 if(blockParticles){
    1157.                     blockParticles.transform.position = Camera.main.transform.position + Camera.main.transform.forward * (blockParticlesPos + CameraControlComponent.zoomDistance + CameraControlComponent.currentDistance);
    1158.                     foreach (Transform child in blockParticles.transform){//emit all particles in the particle effect game object group stored in blockParticles var
    1159.                         blockParticleSys = child.GetComponent<ParticleSystem>();
    1160.                         blockParticleSys.Emit(Mathf.RoundToInt(blockParticleSys.emission.rateOverTime.constant));//emit the particle(s)
    1161.                     }
    1162.                 }
    1163.                 blockState = true;
    1164.             }
    1165.         }
    1166.        
    1167.         timeLastDamaged = Time.time;
    1168.  
    1169.         Quaternion painKickRotation;//Set up rotation for pain view kicks
    1170.         int painKickUpAmt = 0;
    1171.         int painKickSideAmt = 0;
    1172.        
    1173.         if(!invulnerable){
    1174.             hitPoints -= damage;//Apply damage
    1175.         }
    1176.    
    1177.         //set health hud value to hitpoints remaining
    1178.         HealthText.healthGui = Mathf.Round(hitPoints);
    1179.         HealthText2[1].healthGui = Mathf.Round(hitPoints);
    1180.            
    1181.         //change color of hud health element based on hitpoints remaining
    1182.         if (hitPoints <= 25.0f){
    1183.             healthGuiText.material.color = Color.red;
    1184.         }else if (hitPoints <= 40.0f){
    1185.             healthGuiText.material.color = Color.yellow;  
    1186.         }else{
    1187.             healthGuiText.material.color = HealthText.textColor;  
    1188.         }
    1189.        
    1190.         if(!blockState){
    1191.             GameObject pf = Instantiate(painFadeObj) as GameObject;//Create instance of painFadeObj
    1192.             painFadeColor = PainColor;
    1193.             painFadeColor.a = (damage / 5.0f);//fade pain overlay based on damage amount
    1194.             pf.GetComponent<PainFade>().FadeIn(painFadeColor, painTexture, 0.75f);//Call FadeIn function in painFadeObj to fade screen red when damage taken
    1195.         }
    1196.            
    1197.         if(!FPSWalkerComponent.holdingBreath){
    1198.             //Play pain sound when getting hit
    1199.             if(!blockState){//don't play hit sound if blocking attack
    1200.                 if (Time.time > gotHitTimer && painBig && painLittle) {
    1201.                     // Play a big pain sound
    1202.                     if (hitPoints < 40.0f || damage > 30.0f) {
    1203.                         otherfx.clip = painBig;
    1204.                         otherfx.PlayOneShot(otherfx.clip, 1.0f);
    1205.                         gotHitTimer = Time.time + Random.Range(.5f, .75f);
    1206.                     } else {
    1207.                         //Play a small pain sound
    1208.                         otherfx.clip = painLittle;
    1209.                         otherfx.PlayOneShot(otherfx.clip, 1.0f);
    1210.                         gotHitTimer = Time.time + Random.Range(.5f, .75f);
    1211.                     }
    1212.                 }
    1213.             }
    1214.         }else{
    1215.             if (Time.time > gotHitTimer && painDrown) {
    1216.                 //Play a small pain sound
    1217.                 otherfx.clip = painDrown;
    1218.                 otherfx.PlayOneShot(otherfx.clip, 1.0f);
    1219.                 gotHitTimer = Time.time + Random.Range(.5f, .75f);
    1220.             }  
    1221.         }
    1222.        
    1223.         if(!CameraControlComponent.thirdPersonActive){
    1224.             painKickUpAmt = Random.Range(100, -100);//Choose a random view kick up amount
    1225.             if(painKickUpAmt < 50 && painKickUpAmt > 0){painKickUpAmt = 50;}//Maintain some randomness of the values, but don't make it too small
    1226.             if(painKickUpAmt < 0 && painKickUpAmt > -50){painKickUpAmt = -50;}
    1227.            
    1228.             painKickSideAmt = Random.Range(100, -100);//Choose a random view kick side amount
    1229.             if(painKickSideAmt < 50 && painKickSideAmt > 0){painKickSideAmt = 50;}
    1230.             if(painKickSideAmt < 0 && painKickSideAmt > -50){painKickSideAmt = -50;}
    1231.            
    1232.             //create a rotation quaternion with random pain kick values
    1233.             painKickRotation = Quaternion.Euler(mainCamTransform.localRotation.eulerAngles - new Vector3(painKickUpAmt, painKickSideAmt, 0));
    1234.            
    1235.             //make screen kick amount based on the damage amount recieved
    1236.             if(zoomed && !WeaponBehaviorComponent.zoomIsBlock){
    1237.                 appliedPainKickAmt = (damage / (painScreenKickAmt * 10)) / 3;  
    1238.             }else{
    1239.                 appliedPainKickAmt = (damage / (painScreenKickAmt * 10));          
    1240.             }
    1241.            
    1242.             if(blockState){
    1243.                 appliedPainKickAmt = 0.025f;
    1244.             }
    1245.            
    1246.             //make sure screen kick is not so large that view rotates past arm models
    1247.             appliedPainKickAmt = Mathf.Clamp(appliedPainKickAmt, 0.0f, 0.15f);
    1248.            
    1249.             //smooth current camera angles to pain kick angles using Slerp
    1250.             mainCamTransform.localRotation = Quaternion.Slerp(mainCamTransform.localRotation, painKickRotation, appliedPainKickAmt );
    1251.         }
    1252.        
    1253.         if(WeaponBehaviorComponent.zoomIsBlock){
    1254.             if(!WeaponBehaviorComponent.hitCancelsBlock){
    1255.                 blockState = false;
    1256.             }else{
    1257.                  zoomed = false;
    1258.             }
    1259.         }
    1260.    
    1261.         //Call Die function if player's hitpoints have been depleted
    1262.         if (hitPoints < 1.0f){
    1263.             SendMessage("Die");//use SendMessage() to allow other script components on this object to detect player death
    1264.         }
    1265.     }
    1266.  
    1267.     public void ApplyDamageEmerald ( object[] DamageArray ){//damage function for Emerald AI asset
    1268.         ApplyDamage((float)DamageArray[0], (Transform)DamageArray[1], (bool)DamageArray[2]);
    1269.     }
    1270.    
    1271.     void Die () {
    1272.        
    1273.         bulletTimeActive = false;//set bulletTimeActive to false so fadeout wont take longer if bullet time is active
    1274.        
    1275.         if(!FPSWalkerComponent.drowning){
    1276.             //play normal player death sound effect if the player is on land
    1277.             otherfx.clip = die;
    1278.             otherfx.PlayOneShot(otherfx.clip, 1.0f);
    1279.  
    1280.         }else{
    1281.             //play drowning sound effect if the player is underwater    
    1282.             otherfx.clip = dieDrown;
    1283.             otherfx.PlayOneShot(otherfx.clip, 1.0f);
    1284.         }
    1285.        
    1286.         //disable player control and sprinting on death
    1287.         FPSWalkerComponent.inputX = 0;
    1288.         FPSWalkerComponent.inputY = 0;
    1289.         FPSWalkerComponent.cancelSprint = true;
    1290.            
    1291.         GameObject llf = Instantiate(levelLoadFadeObj) as GameObject;//Create instance of levelLoadFadeObj
    1292.         //call FadeAndLoadLevel function with fadein argument set to false
    1293.         //in levelLoadFadeObj to restart level and fade screen out from black on level load
    1294.         llf.GetComponent<LevelLoadFade>().FadeAndLoadLevel(Color.black, 2.0f, false);
    1295.        
    1296.     }
    1297.    
    1298.     public void RestartMap () {
    1299.         Time.timeScale = 1.0f;//set timescale to 1.0f so fadeout wont take longer if bullet time is active
    1300.         GameObject llf = Instantiate(levelLoadFadeObj) as GameObject;//Create instance of levelLoadFadeObj
    1301.         //call FadeAndLoadLevel function with fadein argument set to false
    1302.         //in levelLoadFadeObj to restart level and fade screen out from black on level load
    1303.         llf.GetComponent<LevelLoadFade>().FadeAndLoadLevel(Color.black, 2.0f, false);
    1304.         //set restarting var to true to be accessed by FPSRigidBodyWalker script to stop rigidbody movement
    1305.         restarting = true;
    1306.         // Disable all scripts to deactivate player control upon player death
    1307.         FPSWalkerComponent.inputX = 0;
    1308.         FPSWalkerComponent.inputY = 0;
    1309.         FPSWalkerComponent.cancelSprint = true;
    1310.         WeaponBehaviorComponent.shooting = false;
    1311.     }
    1312.  
    1313. }
    secondly i have AI designer pro and already contacted them still awaiting their reply but just curious as i tried to implement their ai component onto the soldiers, robots and zombies and they will literally just fly off the map but unsure if it is compatible or if that is my fault :/
     
  20. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Save System for Realistic FPS Prefab

    The Save System for Realistic FPS Prefab version 1.02 is now available on the Asset Store!
    (Still at the same low price!)

    This update adds:
    • Optional scene transitions (e.g., fade out) and loading scenes.
    • Auto Save/Load component. Useful for mobile games (save when closing; resume when re-opening).
     
    Weblox likes this.
  21. Deleted User

    Deleted User

    Guest

    This is related to how the shot origin and direction is calculated in third person mode. The shot is intended to hit where the crosshair is pointed, but there might be some ways to improve this. Thanks for your feedback.


    Hi, I have not been able to recreate the first issue you mentioned. There recently was a jumping animation added for weapons, but I just wanted to check that it wasn't something else, like a framerate-induced oscillation of the animation amounts. This could be the case if the weapon bounced rapidly up and down before returning to center, as opposed to slowly bouncing once or twice, which is intended.

    If you don't want the jumping animations, you can un-check the Jumping Animations box in the Movement Options section of the FPSRigidBodyWalker.cs component.

    The idle animation warning is a rigging mismatch and can be ignored. The billboard shader should be updated too if you're seeing that error, which shows up in new Unity versions with the outdated billboard shader. This will be replaced with new assets soon. Thanks for your patience.


    There is a script component called MovePlayerAndCamera.cs attached to the FPS Camera object (deactivated by default) which contains a public method called ReleaseMainCamera() which will handle all the needed variables to turn off the player and allow the camera to be moved freely. You could call this before activating the RTS camera and it should work.


    This is a great idea, stagger, flinching, and knock-back add a lot of strategy and depth to combat. It would probably not be available in the upcoming version, but it would be a great addition for melee combat. This feature would involve freezing player attacks and movement, then playing a stagger camera and weapon animation. The WeaponBehavior.cs and FPSPlayer.cs scripts are probably where you would add this code. Sorry I don't have a specific example on how to do this, but I can answer any more questions you have about it.


    That's a neat idea, you could start by looking at the coroutines Shoot() and AttackTarget() in AI.cs. Shoot() controls the timing of the attacks and AttackTarget() determines the conditions when an attack should start. These methods could be changed for the draw and holster type of gameplay you mentioned.


    Hi, good to hear you're enjoying the project! It sounds like the HitTarget() method in the ArrowObject.cs script does not have a check for the Tactical Shooter AI damage method. You could look at how the scripts communicate the damage event and amounts for the other weapons, and then add that method to either the HitTarget() method of ArrowObject.cs, or to the Tactical Shooter AI damage script. Hope that helps.


    As for the next update the Realistic FPS Prefab, progress is going well. It will mostly be an animation focused update, but it will improve the usability and visuals of the asset.

    @magique I ended up writing new step climbing/step height code for the player controller, so invisible ramps and colliders won't be needed anymore. You can send an email if you'd like this feature before the next update.

    Here is some more good news :)
     
    Weblox likes this.
  22. Napisal

    Napisal

    Joined:
    Apr 26, 2017
    Posts:
    3
    Hi, can you pls explain how do you fix that issue, I got same

    UPD: problem solved by updating asset :)
     
    Last edited: Jun 3, 2017
  23. petercoleman

    petercoleman

    Joined:
    Feb 21, 2016
    Posts:
    475
    "As for the next update the Realistic FPS Prefab, progress is going well. It will mostly be an animation focused update, but it will improve the usability and visuals of the asset."

    I am hoping that some of that may be focused on TP Player animations and make me happy :)

    "I ended up writing new step climbing/step height code for the player controller, so invisible ramps and colliders won't be needed anymore."

    That's good news and helpful particularly since updating my projects to the latest RFPS Prefab V1.27 and the latest Unity versions as I have had a lot of niggling issues crop up from most tags and layers being lost and having to be all found and updated through to AI path finding and collision issues and more.....

    AI enemies have problems now with me in recognising many static objects correctly when they did so previously. e.g. their obstacle avoidance is poor when close to walls/corners/doorways and they clip through them --- and shoot through them at the player. They do this only in some object instances - the same objects/static that existed in previous versions - no change in the level objects (buildings walls) but they see the player through them and shoot at him - they, their bullets and projectile tracers pass straight through them and damage the player. This happens with both static world model entities (meshes) and standard unity objects used for constructing walls that has never happened before....

    Enemies bullets and tracers in particular, visually speaking pass through these walls and leave no impact and they don't actually collide, or the collision is not registering?

    At buildings corners/doorways AI enemies tend to often clip them (despite my upping settings to try and widen their manouvering around obstacles/corners by widening their obstacle avoidance ranges and so on) and when they decide to shoot at the player at a corner if I try and move back from the corner out of sight they often can still see me and shoot directly through the corner of a wall at an angle and their bullet/tracer passes straight through the building wall corner.

    The player (changes to the colliders/navmesh collider) and enemies are also behaving badly with floor collision as well as some enemies (custom models) now seem to not recognise floors so well and tend to float above it and the amount varies and becomes greater the longer they travel - perhaps a gravity/mass thing I don't know. I have played about with their settings endlessly but I seem to have no effect at all on the behaviours. I've tried moving models up/down, settings up/down and so on but to no avail....

    Seems like a zillion glitches and settings to try and go through/change update and try and discover whats going on all round as there's quite a few of these whats some might see as minor things that kill gameplay experience where they never existed previously. I have never really had any of these issues in previous versions to speak of and RFPSP has been really good and stable for me.

    No idea if I am the only one finding these things happening though I have not heard them from anyone else.

    Hopefully an update to RFPSP and Unity may help.

    Peter

    :)
     
  24. ronie635

    ronie635

    Joined:
    Nov 22, 2016
    Posts:
    17
    Hey! Great asset all-in-all, have used if for a few months now. Still learning ofc!
    But at this time it keeps crashing on startup, when I've imported the package to any project (new or existing one). It works fine until i restart Unity, then it won't let me get into the project, just gives me the bug-report screen.

    I've tried it with 5.6.0 and 5.6.1, still keeps crashing.
    I've deleted the files.
    I've re-downloaded the asset pack....
    I cleared the cache-folders in AppData.

    Nothing seems to help, any ideas?
     
  25. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    how do i add weapons i tried the tutorials but it is either one or the other of:
    - Either the gun looks too big when i matched the gun to the size of the other reference materials
    - Gun and hands aren't visible

    is there a step by step guide?
     
  26. Hormic

    Hormic

    Joined:
    Aug 12, 2014
    Posts:
    251
    I have still this annoying errors all the time:
    Code (CSharp):
    1. In order to call GetTransformInfoExpectUpToDate, RendererUpdateManager.UpdateAll must be called first.
    Is there something i can do instead of waiting that it will be fixed from unity?
    Cause its stated "fixed in a future release", which probably means it will be fixed for 2017.1 but never for unity 5.6.
     
  27. Napisal

    Napisal

    Joined:
    Apr 26, 2017
    Posts:
    3
    I am newbie in "unity" and coding stuff so maybe I do it wrong. How I understand after seeking in google - problem reason is: enabled interpolation in rigid bodies. When interpolation flag set to: "none interpolation" - error is not appear. But if any one of your object in scene have "enabled interpolation" - error will appear again.
    To make all my objects in scene not use "interpolation" i add few simple lines in "void Update" and "void Awake()" of my pause script (you can add to any script what you want)

    Code (CSharp):
    1.  
    2.     void Awake()
    3.     {
    4.         Rigidbody[] rb = FindObjectsOfType(typeof(Rigidbody)) as Rigidbody[];
    5.         foreach (Rigidbody RigBod in rb)
    6.         {
    7.             RigBod.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.None;
    8.         }
    9.     }
    10.  
    11.     void Update()
    12.     {
    13.         Rigidbody[] rb = FindObjectsOfType(typeof(Rigidbody)) as Rigidbody[];
    14.         foreach (Rigidbody RigBod in rb)
    15.         {
    16.             RigBod.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.None;
    17.         }
    18.  
    How i say before i am newbie and there can be better and more effective way to fix that problem
     
    Hormic likes this.
  28. petercoleman

    petercoleman

    Joined:
    Feb 21, 2016
    Posts:
    475
    Hi Azuline-Studios

    I just want to report what seems to be a bug in the latest version. When the player uses the f key to instruct allies to move to a position this does not seem to work anymore at least not for me as they don't respond and stay put :)
     
  29. AgathaCrup

    AgathaCrup

    Joined:
    Jun 20, 2013
    Posts:
    27
    Hey Every one, been ages since I looked at unity and this asset, last I checked (at least 2/3 years ago) it was a bit tricky swapping out NPCs but this was the cutting edge asset for FPS. I want to create a simple level with zombie characters created in Mixamo, (by the way it's going to change from Aug go get your models for free now) can you point me to a thread, doc where I can read up on how to do this assuming this works with mechanim ( tho that may not matter I can grab a legacy set somewhere ) etc and is easy to do...great to see this is still available and being updated, any one tell me what happened to the guy that originally started it he seemed to disappear or fell ill but was really helpful ?
     
  30. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    Okay, new problem too the grenades have a glitch where if you use all grenades then go to pick up more, the next time you throw the grenade the grenade stays in his hand
     
  31. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    also, just curious how do i get an enemy to ragdoll as when i add the rigidbody the character/enemy falls to the ground and parts run off everywhere
     
  32. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    Okay, desdperately need help with theswapping of npc's as for some reason the joints are disportioned :/
     
  33. Heddric

    Heddric

    Joined:
    May 24, 2014
    Posts:
    1
    Having issues with the Checkpoint system with the latest version.

    I updated to the latest release of RFPS and now the checkpoint system is not working properly. I re-followed the steps (as close as I could) but some of the lines that are required to be removed do not exist. Now when I run the game, it runs fine and changes the spawnpoint, but when respawning, I get the following error:

    NullReferenceException: Object reference not set to an instance of an object
    LevelLoadFade+<DoFadeOut>c__Iterator1.MoveNext () (at Assets/RFPSP/Scripts/Effects/LevelLoadFade.cs:64)
    UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)
    UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
    LevelLoadFade:FadeAndLoadLevel(Color, Single, Boolean) (at Assets/RFPSP/Scripts/Effects/LevelLoadFade.cs:31)
    FPSPlayer:Die() (at Assets/RFPSP/Scripts/Player/FPSPlayer.cs:1395)
    UnityEngine.Component:SendMessage(String)
    FPSPlayer:ApplyDamage(Single, Transform, Boolean) (at Assets/RFPSP/Scripts/Player/FPSPlayer.cs:1364)
    <Detonate>c__Iterator1:MoveNext() (at Assets/RFPSP/Scripts/Objects/!Destructibles/ExplosiveObject.cs:127)
    UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

    any thoughts?
     
  34. Arealjighead

    Arealjighead

    Joined:
    Apr 7, 2017
    Posts:
    32
    @o0neza0o you have to make sure you have the correct joints selected when setting up a ragdoll. Otherwise what you've described will happen, the limbs will stretch abnormally.
     
  35. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    i'm not sure how to set it up XD
     
  36. C_Occlusion

    C_Occlusion

    Joined:
    Jun 4, 2012
    Posts:
    44

    Thanks so much for this fix...I have been trying to fix this for 3 days now...I just bought RFPSP last week and have found it to be awesome...I know this error was with Unity and not RFPSP...Thanks again for the fix...
     
    Napisal likes this.
  37. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    Hey guys is there a way to integrate ai designer pro?
     
  38. ronie635

    ronie635

    Joined:
    Nov 22, 2016
    Posts:
    17
    Still struggliling with this one... tried it with 5.5.0 aswell, but nothing works
     
  39. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260

    Main Menu Not Showing up on the Gear VR

    Unity: 5.4.0f3 RPFS v: 1.24 Android 5.0 on Samsung s7 Oculus SDK 1.1.0

    OK…. So I have an odd error that I can’t figure out. I have built out a game with RFPS for the Gear VR. I have it all running great, except I just went to add in the Pixel Crushers Save for RFPS script and went to test on the device and realized the entire RFPS main menu does not show when running in the Gear VR.. Although the “Help Text” screen does. The menu does work perfectly in the Unity Editor on the Pc though with target build set to “Android”

    I think I have noticed this before, but in all the bug squashing I was doing, this error just kinda fell off the radar.

    And I am at a loss as to where to look for a solution. I just checked my controller inputs (through Rewired) and this does not seem to be the issue. Could it be a layering issue with the RSPF prefab? Might it be that the GUI was built on a legacy version that the Oculus SDK does not support?

    I also noticed that the Rewired “Control Mapper” prefab, that is used to allow the end user to reconfigure their controller, does not work on the device either, but works perfectly in the Unity editor. So I’m wondering in its an Oculus SDK/Android issue of some sort? I have no idea. But would like to get it fixed as it’s the last big bug I have

    Anyway, anyone’s thoughts on this as to the how or why, would be greatly appreciated.



    Cheers!
     
  40. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Legacy Unity GUI and Unity UI Screen Space Overlay canvases aren't visible in VR. You have to use a Unity UI Screen Space Camera or World Space canvas. (Rewired's Control Mapper also uses Legacy Unity GUI. <- Correction: Uses Unity UI.)

    Hooking up the Save System to a Unity UI canvas is pretty easy. Just point the UI Button's OnClick event to the Save System GameObject's SaveSystem.SaveToSlot or LoadFromSlot method.

    Alternatively, you can implement something like Alien:Isolation and have the "save button" be an interactable object in the game world.
     
    Last edited: Jun 14, 2017
  41. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,609
    Control Mapper uses Unity's 4.6+ UI, not the legacy. It should be fully compatible.

    @jons190

    I will need more information from you to determine what's going on. Please contact me on the Rewired thread, on the support form on the website, or via PM.
     
  42. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    Hey guys i emailed @AzulineStudios about AI and i think there is a way of getting it to work but only problem i am finding at this point is i'm kinda curious if the player shoots in cover where do i place the animations?
     
  43. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Oops, sorry for the misinformation!
     
  44. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,609
    NP!
     
  45. o0neza0o

    o0neza0o

    Joined:
    Sep 6, 2015
    Posts:
    165
    Okay, i need help with not the points system but basicall part of it as i want something along the lines of
    if player has < 0
    player cannot purchase weapons/ammo/upgrades/upgraded ammo
    but if player has = weapon price
    player can buy the weapon.

    but unsure how to implement :/
     
  46. TheChairMaster64

    TheChairMaster64

    Joined:
    Aug 9, 2016
    Posts:
    59
    So it's been a while but the Rupture Dev is back with some more questions. First question is there a way for weapons to use the same ammo. Second so this might be confusing but when I land a hit on a enemy I want them to flash / highlight in red for 1sec maybe faster examples: Metroid Prime and Maybe Mario and Zelda. (Oh And If You Don't Know Metroid Prime 4 is finally Coming so much hype :) ) oh and if I'm not to lazy I'll upload a link for a whole kit for free. Its a low poly weapons/attachment/equipment kit that sadly wasn't good enough for the asset store.
     
  47. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Maybe start with an inventory plugin. Inventory Master is free and includes source code that you could modify to use your score variable as currency. The other two programming challenges are:
    • Stopping RFPS control while shopping, and
    • Updating the weapons available to the RFPS player after purchasing items.
    If you have the Dialogue System for Unity, it includes free integration with RFPS and S-Inventory, so this wouldn't require any programming if you use S-Inventory. Note that the Dialogue System has its own save system, so you don't need to use the Save System for Realistic FPS Prefab. You can download a free evaluation copy of the Dialogue System here.

    Not easily. Each weapon has its own separate ammo type. You could fake it. Let's say you want the AK47 and Sniper rifle to use the same ammo. When you decrease (or increase) the ammo for the AK47, you could also set the Sniper's ammo to the same value, and vice-versa.

    I suggest adding a UnityEvent to CharacterDamage.cs, similar to the OnDie() event mentioned earlier in this email thread. Currently that section of CharacterDamage.cs looks like this:
    Code (csharp):
    1. //Kill NPC
    2. if (hitPoints <= 0.0f){
    3.     onDie.Invoke();
    4.     ...
    5. }
    But you could define an OnDamage UnityEvent and change the code to look like this:
    Code (csharp):
    1. //Kill NPC
    2. if (hitPoints <= 0.0f){
    3.     onDie.Invoke();
    4.     ...
    5. } else {
    6.     onDamage.Invoke();
    7. }
    Then hook up your flash effect to the OnDamage() event in the inspector.

    There are some flash effects on the Asset Store. You could also swap out the shader or material temporarily with a red version. For example, assign a method like this:
    Code (csharp):
    1. public float flashDuration;
    2. public Material flashMaterial;
    3. private Material originalMaterial;
    4. private Renderer myRenderer;
    5.  
    6. void Start() {
    7.     myRenderer = GetComponent<Renderer>();
    8.     originalMaterial = myRenderer.material;
    9. }
    10.  
    11. public void Flash() {
    12.     myRenderer.material = flashMaterial;
    13.     Invoke("UseOriginalMaterial", flashDuration);
    14. }
    15.  
    16. void UseOriginalMaterial() {
    17.     myRenderer.material = originalMaterial;
    18. }
    (Note: I typed this straight into the reply; there may be typos.)
     
  48. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260
    -------------------------
    Picked up the thread over in the rewired thread. Cheers!
     
  49. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260
    Hey Tony. Thanks for pointing me in the right direction. Now I'm learning everything to know about the UNITY GUI system! ;-)


    But I just downloaded and took a look at the new version of the Save system and am intrigued by the "mobile save on quit/start" option you implemented. I may just go with this as a streamlined save/start solution, maybe throw in some checkpoint saves...... and cut out the entire menuing system all-to-gather. I only really needed menuing for game saves and loads.....

    Is there an option to "automatically save from last checkpoint"? in the new mobile save system? That could be super easy to build game dynamics around. Cheers Mate!
     
  50. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    I'll add that as an option. Right now, the AutoSaveLoad component automatically saves to slot 1 when you exit or minimize the game, and it loads slot 1 when you start the game. (Actually when you start the first scene that has the AutoSaveLoad component; you can have a title screen/menu scene before that scene if you want.)

    I'll add an option to not save on exit. In this case, it will only save at checkpoints.


    BTW...
    Save System for Realistic FPS Prefab 1.03 Available

    This is a small update from 1.02. AutoSaveLoad now has options to save on minimize and/or on losing application focus.