Search Unity

Realistic FPS Prefab [RELEASED]

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

  1. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260
    Hey A question for the group.

    I would like to add a few different attack animations to my melee zombie monsters.

    Right now, I can swap any attack animation out from my zombie monster prefab, but I only get the one. Does anyone know of a way to add a couple of different melee attack animations and have them randomly play at attack time so I can get some variance to my NPC melee attack patterns?

    I suspect heavy C# moding to the NPC attack script, but it's beyond my abilities to scratch code that sort of thing out of the blue!

    Cheers mates! Long live RFPS!!!!!!!
     
    OZAV likes this.
  2. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299
    Just to give you an idea, this like used ... with animator, but still simple to understand, to give you an idea (it's not that difficult to do, btw):
    1. void Attack() {
    2. int randomNumber = Random.Range(1, 4);
    3. anim.SetTrigger("atk" + randomNumber);
    4. }
    5. so, it's the basic trick to get the random things fired, as a general idea.
    6. That's if used with the animator, but naked code and directly onto (your) extra attached animations for the purpose - the new anims you want to use will first need to be matching the existing ones in the terms of the import options and size, I guess ... but anyways - this is the basic idea how is done, in the both options, hope it helps, btw, don't be afraid to dig in the code (just make a complete project backup on that day first, before you start the code excavations) :).
     
    jons190 likes this.
  3. twangydave

    twangydave

    Joined:
    Mar 30, 2017
    Posts:
    41
    Sage advice as always Tony.

    I've been away from the forum and happily working away at my project unaware that RFPS was no more. About 6 months ago, I said enough was enough and I would no longer update my Unity version or lust after assets that were not compatible with my version. Before that, I seemed to spend all my (limited) unity time fixing stuff that broke with updates or when I imported new assets.

    I'm just using what I've got now and steadily reducing the scope of my project and feeling much more confident that I will get to the finishing line.

    I am gutted to hear about RFPS though, it's the only FPS kit available that comes close to the 'feel' of the commercial AAA stuff. It has a weight and a heft and a solidity with both the gunplay and the movement that is missing from all the others. In comparison, the others feel 'skatey' and lightweight and a bit amateur.

    As someone who came to this purely as a seasoned FPS gamer, I knew that none of the other kits would cut the mustard even from just watching videos of them. They did not convince me - so how could they convince my player? If RFPS had not been around I would probably not have done an FPS.

    I sincerely hope that this is not the last we see of the package or the most excellent and helpful community that has sprung up around it.
     
    Weblox likes this.
  4. halo_of_the_sun

    halo_of_the_sun

    Joined:
    Sep 17, 2017
    Posts:
    64
    Hey @TonyLi I'm using your Save System and it all works great, but having an issue on one of my builds: If I button-mash as the Player hits a Scene Portal it will skip over the loading scene and all the saved data will be gone in the next scene. It works perfectly in the Editor but not in a build, any ideas why that would be happening?
     
  5. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    Hi @vincent_lade - Scene Portals and the loading scene don't read any input, so let's try to find out what else is jumping in there and interrupting it.

    What buttons are you mashing? Are any particular buttons more likely to cause this?

    Feel free to send a reproduction project to tony (at) pixelcrushers.com. I'll be happy to take a look.
     
  6. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260
    Ya! This is the exact stuff. I wasn't sure how to fire off the random number generator stuff. Setting up the animations I have down pat though. I will see if I can't churn out some code on this. With the help of everyne here I have gone from complete Noob with code, to maybe "sort S***ty, but can cobble scripts together kinda" now as a programmer! ;-)
     
  7. TheChairMaster64

    TheChairMaster64

    Joined:
    Aug 9, 2016
    Posts:
    59
    I would like to know if anyone knows or has found a way to add health bars above enemies and health bars for breakable objects so that its easier to tell if your breaking something or hurting a boss type character.
     
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    If you're OK with showing them at all times, just add a script that sets a world space UI slider's value according to the enemy's CharacterDamage.hitPoints or breakable's BreakableObject.hitPoints.

    If you only want to show them when they've been damaged, you'll need to modify CharacterDamage.ApplyDamage and BreakableObject.ApplyDamage to show the world space UI for a time.
     
  9. F0GZ

    F0GZ

    Joined:
    Feb 22, 2018
    Posts:
    33
    I did a weapon grip system. If someone need it, i can share how to modify code, its pretty simple.
     
    idibil, OZAV and TonyLi like this.
  10. F0GZ

    F0GZ

    Joined:
    Feb 22, 2018
    Posts:
    33
    This guy asked me in PM for help in adding a weapon grip. I want to post here to help others too.

    upload_2019-2-28_14-50-33.png

    This is my personal way, bugs are possible, and if you know how to fix them, write me in PM

    So, the first of all, u need two types of animations for each weapon you want see with grip.

    upload_2019-2-28_14-53-6.png

    Next step: adding some lines in WeaponBehavior.cs

    upload_2019-2-28_14-55-24.png
    Code (CSharp):
    1. public bool haveGrip;
    upload_2019-2-28_14-56-16.png
    Code (CSharp):
    1. if (!haveGrip)
    2.                         {
    3.                             WeaponAnimatorComponent.SetTrigger("Ready");
    4.                         }
    5.                         else
    6.                         {
    7.                             WeaponAnimatorComponent.SetTrigger("ReadyGrip");
    8.                         }
    upload_2019-2-28_14-57-6.png
    Code (CSharp):
    1. if (!haveGrip)
    2.                                         {
    3.                                             WeaponAnimatorComponent.SetTrigger("Reload");
    4.                                         }
    5.                                         else
    6.                                         {
    7.                                             WeaponAnimatorComponent.SetTrigger("ReloadGrip");
    8.                                         }

    NEXT MESSAGE
     
    OZAV and Weblox like this.
  11. F0GZ

    F0GZ

    Joined:
    Feb 22, 2018
    Posts:
    33
    upload_2019-2-28_14-58-16.png
    Code (CSharp):
    1. if (!haveGrip)
    2.                                 {
    3.                                     WeaponAnimatorComponent.SetTrigger("Fire");
    4.                                 }
    5.                                 else
    6.                                 {
    7.                                     WeaponAnimatorComponent.SetTrigger("FireGrip");
    8.                                 }
    upload_2019-2-28_14-58-46.png
    Code (CSharp):
    1.  if (!haveGrip)
    2.                 {
    3.                     WeaponAnimatorComponent.SetTrigger("Fire");
    4.                 }
    5.                 else
    6.                 {
    7.                     WeaponAnimatorComponent.SetTrigger("FireGrip");
    8.                 }
    upload_2019-2-28_14-59-18.png
    Code (CSharp):
    1. if (!haveGrip)
    2.                         {
    3.                             WeaponAnimatorComponent.SetTrigger("Reload");
    4.                         }
    5.                         else
    6.                         {
    7.                             WeaponAnimatorComponent.SetTrigger("ReloadGrip");
    8.                         }
    upload_2019-2-28_14-59-56.png
    Code (CSharp):
    1. if (!haveGrip)
    2.                         {
    3.                             WeaponAnimatorComponent.SetTrigger("Reload");
    4.                         }
    5.                         else
    6.                         {
    7.                             WeaponAnimatorComponent.SetTrigger("ReloadGrip");
    8.                         }

    Next step: adding some animator things and set triggers

    upload_2019-2-28_15-1-6.png
     
    C_Occlusion, Mark_01 and Weblox like this.
  12. F0GZ

    F0GZ

    Joined:
    Feb 22, 2018
    Posts:
    33
    NOTE!
    Reccomend to turn off automatic reload corountine

    upload_2019-2-28_15-2-29.png

    I'm not a programmer, I'm an animator, so my code modification may seem very primitive, but in any case, everything works.

    If the tutorial was useful for you, support, subscribe to the social networks of my game, please!

    Projects:

    "03.04" - https://store.steampowered.com/app/952950/0304/

    Links:
    Facebook: fb.me/jpegofpain
    Youtube: www.youtube.com/channel/UC5VzCmo2LpIXmamGB8caLiw
    VK: vk.com/jpegofpaingames

    Contact me: mishanotest@gmail.com
     

    Attached Files:

    Last edited: Feb 28, 2019
    idibil, jons190, Mark_01 and 2 others like this.
  13. Weblox

    Weblox

    Joined:
    Apr 11, 2016
    Posts:
    277

    So I do have a healthbar Script working with a Canvas that is put inside the Enemy Hierarchy. If you want to take it a step further you could add a OnHurt and a OnDead Event to your RFPS CharacterDamage.cs to activate the Canvas in the OnHurt Event, then deactivate it in OnDead Event. This way the Enemy Healthbar will start disabled, then show when the AI Enemy takes its first damage and be disabled on the Enemies death. However, I did not come up with the Script myself and honestly I do not remember absolutely sure where it originated, so I suppose it was @TonyLi who was so kind to share it. If it is Okay to do so, I will happily post a .rar containing the Canvas and the Script for everyone who still need it.

    >> Healthbar attached. <<


    @all: For my little own Project I am trying to add a Functionality to The RFPS Spawner Script, that will give a checkbox to spawn all AI to a group ("Flock") under the Spawner Game Object (Parent) and another checkbox to spawn all AI to a New Game Object (Parent) with the Option to define the New Game Objects name in a textfield. I encountered this functionality using another Asset and was able to spot the Function in its according Script, but terribly failed to implement it to the RFPS Spawner.

    Any help with this would be much appreciated
    .
    Screenshot (from original Asset):

    Spawn to Group.PNG
     

    Attached Files:

    Last edited: Feb 28, 2019
    NickNovell and Mark_01 like this.
  14. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    Try this: Say you've added these variables at the top of the script:
    Code (csharp):
    1. public bool groupToNewGameObject = false;
    2. public string newGameObjectName;
    3. private GameObject newParent = null;
    After this line:
    Code (csharp):
    1. NPCInstance = Instantiate(NpcPrefab,transform.position,transform.rotation) as GameObject;
    add something like this:
    Code (csharp):
    1. if (!groupToNewGameObject) {
    2.     NPCInstance.transform.SetParent(this.transform);
    3. } else {
    4.     if (newParent == null) newParent = new GameObject(newGameObjectName);
    5.     NPCInstance.transform.SetParent(newParent.transform);
    6. }
     
    C_Occlusion, Mark_01 and Weblox like this.
  15. Weblox

    Weblox

    Joined:
    Apr 11, 2016
    Posts:
    277
    @TonyLi - Thank you so much for this! Once again you are a true lifesaver for my little game. I already have it up and running and everything seems to work perfectly. I will try and add this to all the Spawners throughout my Projects. I updated my first Post with the Healthbar also, just let me know if it should be deleted later.

    Again. thanks a lot and keep up the good work !! :p
     
    Last edited: Feb 28, 2019
    Mark_01 likes this.
  16. TheChairMaster64

    TheChairMaster64

    Joined:
    Aug 9, 2016
    Posts:
    59
    @Weblox - You didn't have to do that but thanks a lot man means a lot man it really helps with feedback with a long boss fight and knowing your actually doing something!!! @TonyLi your also alot of help since the start of my project. I did plan on trying to figure out how that script would be made but im simply not a coder. My project wouldn't have got as far as it has gotten without this forum. Thankssss:);)
     
    Weblox likes this.
  17. Mario167100

    Mario167100

    Joined:
    Jul 25, 2016
    Posts:
    49
    Um, i wanted to know how I can get rid of the health counter and replace it with a health bar instead. I just wanted to know how exactly i could do that.
     
    Last edited: Mar 5, 2019
  18. NickNovell

    NickNovell

    Joined:
    Apr 27, 2017
    Posts:
    51
  19. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299
    just a note ...for you guys, to save you from a (loads) of problems with those health bar mess'es: new version of Emerald AI (V.2,2 currently) has tickable-untickable health bars coded in now, so if you want to build enemies via emerald- it comes included. (Just tick it on in the options when you want to have it, for any enemy), and new code and features version v2.2 currently is fantastic, it has melee and projectiles based enemies now as well, so that's the (one) way to go about health bars, and stay more on the 'safe' quality side, if it helps, as another option I would highly recommend here, knowing the new quality of Emerald by now, and - also - it has RFPS integration guide now, as well, with this current fresh version V2.2 ... I have also contacted the dev's as well to add the option for enemies to walk on the walls, as a next step, (eg spiders, ants and what-not) so we will see ... that's been noted too, by the dev's, on their to-do ... :). https://www.assetstore.unity3d.com/en/?stay/search?q=on_sale:yes#!/content/40199
     
    Last edited: Mar 7, 2019
  20. DanielDoria

    DanielDoria

    Joined:
    May 6, 2018
    Posts:
    3
    Hi! After updating the 2018 unity for March version my RFPSP is with very low NPC sounds, how to fix it?
     
  21. SickaGames1

    SickaGames1

    Joined:
    Jan 15, 2018
    Posts:
    1,270
    This got deprecated?
     
  22. NickNovell

    NickNovell

    Joined:
    Apr 27, 2017
    Posts:
    51
    Hello, I can't find any instructions of integrading EMERALD AI 2.2 with RFPS. Instructions are for the previous version of Emerald.
     
  23. Oderus_Urungus

    Oderus_Urungus

    Joined:
    Jun 8, 2017
    Posts:
    96
    I've been using this asset a long time on my main game, and I never thought getting shadows disabled for weapons and the main character mesh would be this confusing.
    I have set cast shadows to none on every weapon model in first and third person, in everything in the hierarchy for the tp model, and I still have shadows.

    It's driving me nuts! I have to be missing an exposed toggle in the inspector somewhere.

    Help!!
     
  24. SickaGames1

    SickaGames1

    Joined:
    Jan 15, 2018
    Posts:
    1,270
    Did this go open source?
     
  25. Oderus_Urungus

    Oderus_Urungus

    Joined:
    Jun 8, 2017
    Posts:
    96
    No. It's just deprecated.
     
  26. SickaGames1

    SickaGames1

    Joined:
    Jan 15, 2018
    Posts:
    1,270
    Dang! I wanted a copy!
     
  27. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299
    Yep ... it should be a link (or a txt file inside), i saw it currently leads to the older version of Emerald RFPS integration guide (online), and it's not updated yet ... maybe it's worth letting know the Emerald guys about it, but .. .still ... it gives you a pretty good initial idea ... you can post here what part are you stuck with, so we can help you out a bit with the integration with current V2.2 Emerald ... (*note that any Emerald version prior the current V2.2 is the best to remove completely first, and than import the fresh current V2.2 Emerald, they also advise it to be the best practice, currently) :).
     
  28. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299
    ... just wait for the new rfps version, they often revamp it, each time in a lot better version, as we used to, from the Azuline :).
     
    C_Occlusion likes this.
  29. SickaGames1

    SickaGames1

    Joined:
    Jan 15, 2018
    Posts:
    1,270
    I thought he gave up on it because of not having a lot of time?
     
  30. Oderus_Urungus

    Oderus_Urungus

    Joined:
    Jun 8, 2017
    Posts:
    96

    Anybody?
     
  31. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299
    Well, it's just life I guess, but the best thing about it is, actually: we don't know :).
     
  32. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299
    ... in the aid to our absent prof. Urungus: do you still have the shadows for ALL weapon models or - only for some (I will check that first) ... also, do you have only 1 map where no shadows for weapons are required, and you only use for such tests ? i would make another map and copy that Player version in it, to see if you have the same problem ... that's for starters, for getting a few answers ... also: remember, there is a Main Camera (with it's tickeable option 'dual camera' setup which is to be kept in mind as well), and there is a Weapon Camera, which are not the same - when you select weapon - the weapon camera works. P.S. careful there in the kitchen - your coffee is boiling :).
     
    Last edited: Mar 10, 2019
  33. philc_uk

    philc_uk

    Joined:
    Jun 17, 2015
    Posts:
    90
    Hi!
    The underwater seems to work fine in the editor - however when i do a build (Unity 2017.4), the underwater effects do not work! No fog ect, looks just like above.
    Any idea why?
    Thanks!
     
  34. ble_butter123

    ble_butter123

    Joined:
    Jul 10, 2015
    Posts:
    1
    Hi,
    I really wanted to buy a copy?!?
    I send an email to the info@azulinestudios.com but they didn't replay
    :(
    anyway, hopefully this asset will come back to the store
    A.
     
    OZAV likes this.
  35. ProBrStalker

    ProBrStalker

    Joined:
    Aug 20, 2017
    Posts:
    65
    I haved fix the script
    Code (CSharp):
    1. //AI.cs by Azuline Studios© All Rights Reserved
    2. //Allows NPC to track and attack targets and patrol waypoints.
    3. using UnityEngine;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6.  
    7. public class AI : MonoBehaviour {
    8.     [HideInInspector]
    9.     public bool spawned = false;
    10.     [HideInInspector]
    11.     public GameObject playerObj;
    12.     [HideInInspector]
    13.     public Transform playerTransform;
    14.     [HideInInspector]
    15.     public GameObject NPCMgrObj;
    16.     [HideInInspector]
    17.     public GameObject weaponObj;//currently equipped weapon object of player
    18.     [HideInInspector]
    19.     public FPSRigidBodyWalker FPSWalker;
    20.     [HideInInspector]
    21.     public NPCAttack NPCAttackComponent;
    22.     [HideInInspector]
    23.     public PlayerWeapons PlayerWeaponsComponent;
    24.     private WeaponBehavior WeaponBehaviorComponent;
    25.     [HideInInspector]
    26.     public CharacterDamage TargetCharacterDamageComponent;
    27.     [HideInInspector]
    28.     public CharacterDamage CharacterDamageComponent;
    29.     [HideInInspector]
    30.     public NPCSpawner NPCSpawnerComponent;
    31.     [HideInInspector]
    32.     public NPCRegistry NPCRegistryComponent;
    33.     [HideInInspector]
    34.     public AI TargetAIComponent;
    35.     [HideInInspector]
    36.     public UnityEngine.AI.NavMeshAgent agent;
    37.     [HideInInspector]
    38.     public Collider[] colliders;
    39.     private bool collisionState;
    40.     [HideInInspector]
    41.     public Animation AnimationComponent;
    42.     [HideInInspector]
    43.     public Animator AnimatorComponent;
    44.     private float animSpeed;
    45.     [Tooltip("If true, AI.cs will use Mecanim animations for this NPC.")]
    46.     public bool useMecanim;
    47.     [HideInInspector]
    48.     public bool recycleNpcObjOnDeath;
    49.     [Tooltip("The object with the Animation/Animator component which will be accessed by AI.cs to play NPC animations. If none, this root object will be checked for the Animator/Animations component.")]
    50.     public Transform objectWithAnims;
    51.     [Tooltip("Chance between 0 and 1 that NPC will spawn. Used to randomize NPC locations and surprise the player.")]
    52.     [Range(0.0f, 1.0f)]
    53.     public float randomSpawnChance = 1.0f;
    54.    
    55.     //NPC movement speeds
    56.     [Tooltip("Running speed of the NPC.")]
    57.     public float runSpeed = 6.0f;
    58.     [Tooltip("Walking speed of the NPC.")]
    59.     public float walkSpeed = 1.0f;
    60.     [Tooltip("Speed of running animation.")]
    61.     public float walkAnimSpeed = 1.0f;
    62.     [Tooltip("Speed of walking animation.")]
    63.     public float runAnimSpeed = 1.0f;
    64.     private float speedAmt = 1.0f;
    65.     private float lastRunTime;//to prevent rapid walking, then running when following player
    66.    
    67.     [Tooltip("NPC yaw angle offset when standing.")]
    68.     public float idleYaw = 0f;
    69.     [Tooltip("NPC yaw angle offset when moving.")]
    70.     public float movingYaw = 0f;
    71.     private float yawAmt;
    72.  
    73.     [Tooltip("Sets the alignment of this NPC. 1 = friendly to player and hostile to factions 2 and 3, 2 = hostile to player and factions 1 and 3, 3 = hostile to player and factions 1 and 2.")]
    74.     public int factionNum = 1;//1 = human(friendly to player), 2 = alien(hostile to player), 3 = zombie(hostile to all other factions)
    75.     [Tooltip("If false, NPC will attack any character that attacks it, regardless of faction.")]
    76.     public bool ignoreFriendlyFire;
    77.     [HideInInspector]
    78.     public bool playerAttacked;//to make friendly NPCs go hostile if attacked by player
    79.     [HideInInspector]
    80.     public float attackedTime;
    81.  
    82.     //waypoints and patrolling
    83.     [HideInInspector]
    84.     public Transform myTransform;
    85.     private Vector3 upVec;//cache this for optimization;
    86.     [Tooltip("True if NPC will hunt player accross map without needing to detect player first.")]
    87.     public bool huntPlayer;
    88.     [Tooltip("True if NPC should only follow patrol waypoints once.")]
    89.     public bool patrolOnce;
    90.     [Tooltip("True if NPC should walk on patrol, will run on patrol if false.")]
    91.     public bool walkOnPatrol = true;
    92.     private  Transform curWayPoint;
    93.     [Tooltip("Drag the parent waypoint object with the WaypointGroup.cs script attached here. If none, NPC will stand watch instead of patrolling.")]
    94.     public WaypointGroup waypointGroup;
    95.     [Tooltip("The number of the waypoint in the waypoint group which should be followed first.")]
    96.     public int firstWaypoint = 1;
    97.     [Tooltip("True if player should stand in one place and not patrol waypoint path.")]
    98.     public bool standWatch;
    99.     [Tooltip("True if NPC is following player.")]
    100.     public bool followPlayer;
    101.     [Tooltip("True if NPC can be activated with the use button and start following the player.")]
    102.     public bool followOnUse;
    103.     [Tooltip("True if this NPC wants player to follow them (wont take move orders from player, only from MoveTrigger.cs).")]
    104.     public bool leadPlayer;
    105.     [HideInInspector]
    106.     public bool orderedMove;
    107.     [HideInInspector]
    108.     public bool playerFollow;//true if this NPC wants player to follow them (wont take move orders from player, only from MoveTrigger.cs)
    109.     private float commandedTime;
    110.     private float talkedTime;
    111.     private bool  countBackwards = false;
    112.     [Tooltip("Minimum distance to destination waypoint that NPC will consider their destination as reached.")]
    113.     public float pickNextDestDist = 2.5f;
    114.     private Vector3 startPosition;
    115.     private float spawnTime;
    116.  
    117.     [Tooltip("Volume of NPC's vocal sound effects.")]
    118.     public float vocalVol = 0.7f;
    119.     [Tooltip("Sound to play when player commands NPC to stop following.")]
    120.     public AudioClip stayFx1;
    121.     [Tooltip("Sound to play when player commands NPC to stop following.")]
    122.     public AudioClip stayFx2;
    123.     [Tooltip("Sound to play when player commands NPC to start following.")]
    124.     public AudioClip followFx1;
    125.     [Tooltip("Sound to play when player commands NPC to start following.")]
    126.     public AudioClip followFx2;
    127.     [Tooltip("Sound to play when player commands NPC to move to position.")]
    128.     public AudioClip moveToFx1;
    129.     [Tooltip("Sound to play when player commands NPC to move to position.")]
    130.     public AudioClip moveToFx2;
    131.     [Tooltip("Sound to play when NPC has been activated more than joke activate times.")]
    132.     public AudioClip jokeFx;
    133.     [Tooltip("Sound to play when NPC has been activated more than joke activate times.")]
    134.     public AudioClip jokeFx2;
    135.     [Tooltip("Number of consecutive use button presses that activates joke fx.")]
    136.     public int jokeActivate = 33;
    137.     private float jokePlaying = 0f;
    138.     private int jokeCount;
    139.    
    140.     [Tooltip("Sound effects to play when pursuing player.")]
    141.     public AudioClip[] tauntSnds;
    142.     [Tooltip("True if taunt sound shouldn't be played when attacking.")]
    143.     public bool cancelAttackTaunt;
    144.     private float lastTauntTime;
    145.     [Tooltip("Delay between times to check if taunt sound should be played.")]
    146.     public float tauntDelay = 2f;
    147.     [Tooltip("Chance that a taunt sound will play after taunt delay.")]
    148.     [Range(0.0f, 1.0f)]
    149.     public float tauntChance = 0.5f;
    150.     [Tooltip("Volume of taunt sound effects.")]
    151.     public float tauntVol = 0.7f;
    152.     [Tooltip("Sound effects to play when NPC discovers player.")]
    153.     public AudioClip[] alertSnds;
    154.     [Tooltip("Volume of alert sound effects.")]
    155.     public float alertVol = 0.7f;
    156.     private bool alertTaunt;
    157.    
    158.    
    159.     [HideInInspector]
    160.     public AudioSource vocalFx;
    161.     private AudioSource footstepsFx;
    162.     [Tooltip("Sound effects to play for NPC footsteps.")]
    163.     public AudioClip[] footSteps;
    164.     [Tooltip("Volume of footstep sound effects.")]
    165.     public float footStepVol = 0.5f;
    166.     [Tooltip("Time between footstep sound effects when walking (sync with anim).")]
    167.     public float walkStepTime = 1.0f;
    168.     [Tooltip("Time between footstep sound effects when running (sync with anim).")]
    169.     public float runStepTime = 1.0f;
    170.     private float stepInterval;
    171.     private float stepTime;
    172.  
    173.     //targeting and attacking
    174.     [Tooltip("Minimum range to target to start attack.")]
    175.     public float shootRange = 15.0f;
    176.     [Tooltip("Range that NPC will start chasing target until they are within shoot range.")]
    177.     public float attackRange = 30.0f;
    178.     [Tooltip("Range that NPC will hear player attacks.")]
    179.     public float listenRange = 30.0f;
    180.     [Tooltip("Time between shots (longer for burst weapons).")]
    181.     public float shotDuration = 0.0f;
    182.     [Tooltip("Speed of attack animation.")]
    183.     public float shootAnimSpeed = 1.0f;
    184.     [HideInInspector]
    185.     public float attackRangeAmt = 30.0f;//increased by character damage script if NPC is damaged by player
    186.     [Tooltip("Percentage to reduce enemy search range if player is crouching.")]
    187.     public float sneakRangeMod = 0.4f;
    188.     private float shootAngle = 3.0f;
    189.     [Tooltip("Time before atack starts, to allow weapon to be raised before firing.")]
    190.     public float delayShootTime = 0.35f;
    191.     [Tooltip("Random delay between NPC attacks.")]
    192.     public float randShotDelay = 0.75f;
    193.     [Tooltip("Height of rayCast origin which detects targets (can be raised if NPC origin is at their feet).")]
    194.     public float eyeHeight = 0.4f;
    195.     [Tooltip("Draws spheres in editor for position and eye height.")]
    196.     public bool drawDebugGizmos;
    197. //    [HideInInspector]
    198.     public Transform target = null;
    199. //    [HideInInspector]
    200.     public bool targetVisible;
    201.     private float lastVisibleTime;
    202.     private Vector3 targetPos;
    203.     [HideInInspector]
    204.     public float targetRadius;
    205.     [HideInInspector]
    206.     public float attackTime = -16.0f;//time last attacked
    207.     private bool attackFinished = true;
    208.     private bool turning;//true if turning to face target
    209.     [HideInInspector]
    210.     public bool cancelRotate;
    211.     [HideInInspector]
    212.     public bool followed;//true when npc is moving to destination defined by MoveTrigger.cs
    213.  
    214.     private float targetDistance;
    215.     private Vector3 targetDirection;
    216.     private RaycastHit[] hits;
    217.     private bool sightBlocked;//true if sight to target is blocked
    218.     [HideInInspector]
    219.     public bool playerIsBehind;//true if player is behind NPC
    220.     [HideInInspector]
    221.     public float targetEyeHeight;
    222.     private bool pursueTarget;
    223.     [HideInInspector]
    224.     public Vector3 lastVisibleTargetPosition;
    225.     [HideInInspector]
    226.     public float timeout = 0.0f;//to allow NPC to resume initial behavior after searching for target
    227.     [HideInInspector]
    228.     public bool heardPlayer = false;
    229.     [HideInInspector]
    230.     public bool heardTarget = false;
    231.     [HideInInspector]
    232.     public bool damaged;//true if attacked
    233.     private bool damagedState;
    234.     [HideInInspector]
    235.     public float lastDamageTime;
    236.  
    237.     [HideInInspector]
    238.     public LayerMask searchMask = 0;//only layers to include in target search (for efficiency)
    239.    
    240.     [HideInInspector]
    241.     public RaycastHit attackHit;
    242.    
    243.     //public int navTest;
    244.  
    245.     void Start(){
    246.    
    247.         NPCMgrObj = GameObject.Find("NPC Manager");
    248.         NPCRegistryComponent = NPCMgrObj.GetComponent<NPCRegistry>();
    249.         NPCRegistryComponent.Npcs.Add(myTransform.gameObject.GetComponent<AI>());//register this active NPC with the NPCRegistry
    250.        
    251.         Mathf.Clamp01(randomSpawnChance);
    252.  
    253.         if(Random.value > randomSpawnChance){
    254.             Destroy(myTransform.gameObject);
    255.         }
    256.     }
    257.    
    258.     void OnEnable(){
    259.        
    260.         myTransform = transform;
    261.         upVec = Vector3.up;;
    262.         startPosition = myTransform.position;
    263.         timeout = 0.0f;
    264.         attackedTime = -16f;//set to negative value to prevent NPCs from having larger search radius briefly after spawning
    265.         if(jokeFx){
    266.             jokePlaying = jokeFx.length * -2f;
    267.         }
    268.        
    269.         collisionState = false;
    270.  
    271.         //initialize audiosource for footsteps
    272.         footstepsFx = myTransform.gameObject.AddComponent<AudioSource>();
    273.         footstepsFx.spatialBlend = 1.0f;
    274.         footstepsFx.volume = footStepVol;
    275.         footstepsFx.pitch = 1.0f;
    276.         footstepsFx.dopplerLevel = 0.0f;
    277.         footstepsFx.bypassEffects = true;
    278.         footstepsFx.bypassListenerEffects = true;
    279.         footstepsFx.bypassReverbZones = true;
    280.         footstepsFx.maxDistance = 10.0f;
    281.         footstepsFx.rolloffMode = AudioRolloffMode.Linear;
    282.         footstepsFx.playOnAwake = false;
    283.        
    284.         vocalFx = myTransform.gameObject.AddComponent<AudioSource>();
    285.         vocalFx.spatialBlend = 1.0f;
    286.         vocalFx.volume = vocalVol;
    287.         vocalFx.pitch = 1.0f;
    288.         vocalFx.dopplerLevel = 0.0f;
    289.         vocalFx.bypassEffects = true;
    290.         vocalFx.bypassListenerEffects = true;
    291.         vocalFx.bypassReverbZones = true;
    292.         vocalFx.maxDistance = 10.0f;
    293.         vocalFx.rolloffMode = AudioRolloffMode.Linear;
    294.         vocalFx.playOnAwake = false;
    295.  
    296.         //set layermask to layers such as layer 10 (world collision) and 19 (interactive objects) for target detection
    297.         searchMask = ~(~(1 << 10) & ~(1 << 0) & ~(1 << 13) & ~(1 << 11) & ~(1 << 20));
    298.        
    299.         //if there is no objectWithAnims defined, use the Animation Component attached to this game object
    300.         if(objectWithAnims == null){objectWithAnims = transform;}
    301.  
    302.         if(!useMecanim){//initialize legacy animations
    303.             AnimationComponent = objectWithAnims.GetComponent<Animation>();
    304.             // Set all animations to loop
    305.             AnimationComponent.wrapMode = WrapMode.Loop;
    306.             // Except our action animations, Dont loop those
    307.             AnimationComponent["shoot"].wrapMode = WrapMode.Once;
    308.             // Put idle and run in a lower layer. They will only animate if our action animations are not playing
    309.             AnimationComponent["idle"].layer = -1;
    310.             AnimationComponent["walk"].layer = -1;
    311.             AnimationComponent["run"].layer = -1;
    312.            
    313.             AnimationComponent["walk"].speed = walkAnimSpeed;
    314.             AnimationComponent["shoot"].speed = shootAnimSpeed;
    315.             AnimationComponent["run"].speed = runAnimSpeed;
    316.            
    317.             AnimationComponent.Stop();
    318.         }else{
    319.             AnimatorComponent = objectWithAnims.GetComponent<Animator>();//set reference to Mecanim animator component
    320.         }
    321.        
    322.         //initialize AI vars
    323.         playerObj = Camera.main.transform.GetComponent<CameraControl>().playerObj;
    324.         playerTransform = playerObj.transform;
    325.         PlayerWeaponsComponent = Camera.main.transform.GetComponent<CameraControl>().weaponObj.GetComponentInChildren<PlayerWeapons>();
    326.         FPSWalker = playerObj.GetComponent<FPSRigidBodyWalker>();
    327.         NPCAttackComponent = GetComponent<NPCAttack>();
    328.         CharacterDamageComponent = GetComponent<CharacterDamage>();
    329.  
    330.         //initialize navmesh agent
    331.         agent = GetComponent<UnityEngine.AI.NavMeshAgent>();
    332.         agent.speed = runSpeed;
    333.         agent.acceleration = 60.0f;
    334.  
    335.         //Get all colliders for this NPC's body parts
    336.         colliders = GetComponentsInChildren<Collider>();
    337.        
    338.         attackRangeAmt = attackRange;
    339.  
    340.         if(!useMecanim){
    341.             AnimationComponent.CrossFade("idle", 0.3f);
    342.         }else{
    343.             AnimatorComponent.SetBool("Idle", true);
    344.             AnimatorComponent.SetBool("Walk", false);
    345.             AnimatorComponent.SetBool("Run", false);
    346.         }
    347.  
    348.         if(!spawned){//if spawned, SpawnNPC function will be called from NPCSpawner.cs. Otherwise, spawn now.      
    349.             StopAllCoroutines();
    350.             SpawnNPC();
    351.         }
    352.        
    353.     }
    354.  
    355.     //initialize NPC behavior
    356.     public void SpawnNPC(){
    357.  
    358.  
    359.         if(agent.isOnNavMesh){
    360.             spawnTime = Time.time;
    361.             StartCoroutine(PlayFootSteps());
    362.             if(objectWithAnims != myTransform){
    363.                 StartCoroutine(UpdateModelYaw());
    364.             }
    365.             if(!huntPlayer){
    366.                 //determine if NPC should patrol or stand watch
    367.                 if(!standWatch && waypointGroup && waypointGroup.wayPoints[firstWaypoint - 1]){
    368.                     curWayPoint = waypointGroup.wayPoints[firstWaypoint - 1];
    369.                     speedAmt = runSpeed;
    370.                     startPosition = curWayPoint.position;
    371.                     TravelToPoint(curWayPoint.position);
    372.                     StartCoroutine(Patrol());
    373.                 }else{
    374.                     TravelToPoint(startPosition);
    375.                     StartCoroutine(StandWatch());
    376.                 }
    377.             }else{
    378.                 //hunt the player accross the map
    379.                 playerObj = Camera.main.transform.GetComponent<CameraControl>().playerObj;
    380.                 playerTransform = playerObj.transform;
    381.                 PlayerWeaponsComponent = Camera.main.transform.GetComponent<CameraControl>().weaponObj.GetComponentInChildren<PlayerWeapons>();
    382.                 FPSWalker = playerObj.GetComponent<FPSRigidBodyWalker>();
    383.                 factionNum = 2;
    384.                 target = playerTransform;
    385.                 targetEyeHeight = FPSWalker.capsule.height * 0.25f;
    386.                 lastVisibleTargetPosition = target.position + (target.up * targetEyeHeight);
    387.                 attackRange = 2048.0f;
    388.                 StartCoroutine(AttackTarget());
    389.  
    390.                 speedAmt = runSpeed;
    391.                 TravelToPoint(playerObj.transform.position);
    392.             }
    393.         }else{
    394.             Debug.Log("<color=red>NPC can't find Navmesh:</color> Please bake Navmesh for this scene or reposition NPC closer to navmesh.");
    395.         }
    396.     }
    397.  
    398.     //draw debug spheres in editor
    399.     void OnDrawGizmos() {
    400.         if(drawDebugGizmos){
    401.             Gizmos.color = Color.yellow;
    402.             Gizmos.DrawSphere(transform.position, 0.2f);
    403.             Gizmos.color = Color.red;
    404.             Gizmos.DrawSphere(transform.position + new Vector3(0.0f, eyeHeight, 0.0f), 0.2f);
    405.        
    406.             Vector3 myPos = transform.position + (transform.up * eyeHeight);
    407.             Vector3 targetPos = lastVisibleTargetPosition;
    408.             Vector3 testdir1 = (targetPos - myPos).normalized;
    409.             float distance = Vector3.Distance(myPos, targetPos);
    410.             Vector3 testpos3 = myPos + (testdir1 * distance);
    411.            
    412.             if (Physics.Linecast(myPos, targetPos)) {
    413.                 Gizmos.color = Color.red;
    414.             }else{
    415.                 Gizmos.color = Color.green;
    416.             }
    417.  
    418.             Gizmos.DrawLine (myPos, testpos3);
    419.             Gizmos.DrawSphere(testpos3, 0.2f);
    420.  
    421.            
    422.             if(target){
    423.                 Gizmos.color = Color.yellow;
    424.                 Gizmos.DrawLine (myPos, target.position + (transform.up * targetEyeHeight));
    425.             }
    426.  
    427.             Gizmos.color = Color.green;
    428.             Gizmos.DrawSphere(transform.position + (transform.forward * 0.6f) + (transform.up * eyeHeight), 0.2f);
    429.  
    430.         }
    431.        
    432.     }
    433.    
    434.     IEnumerator StandWatch(){
    435.         while (true) {
    436.  
    437.             if(huntPlayer){
    438.                 SpawnNPC();
    439.                 yield break;
    440.             }
    441.            
    442.             //expand search radius if attacked
    443.             if(attackedTime + 6.0f > Time.time){
    444.                 attackRangeAmt = attackRange * 6.0f;//expand enemy search radius if attacked to defend against sniping
    445.             }else{
    446.                 attackRangeAmt = attackRange;
    447.             }
    448.  
    449.             //allow player to push friendly NPCs out of their way
    450.             if(playerObj.activeInHierarchy && !collisionState && FPSWalker.capsule){
    451.                 foreach(Collider col in colliders){
    452.                     Physics.IgnoreCollision(col, FPSWalker.capsule, true);
    453.                 }
    454.                 collisionState = true;
    455.             }
    456.  
    457.             CanSeeTarget();
    458.             if ((target && targetVisible) || heardPlayer || heardTarget){
    459.                 yield return StartCoroutine(AttackTarget());
    460.             }else{
    461.                 if(NPCRegistryComponent){
    462.                     NPCRegistryComponent.FindClosestTarget(myTransform.gameObject, this, myTransform.position, attackRangeAmt, factionNum);
    463.                 }
    464.             }
    465.             if(attackTime < Time.time){
    466.                 if((!followPlayer || orderedMove) && Vector3.Distance(startPosition, myTransform.position) > pickNextDestDist){
    467.                     if(!orderedMove){
    468.                         speedAmt = walkSpeed;
    469.                     }else{
    470.                         speedAmt = runSpeed;
    471.                     }
    472.                     TravelToPoint(startPosition);//
    473.                 }else if(followPlayer && !orderedMove && Vector3.Distance(playerObj.transform.position, myTransform.position) > pickNextDestDist){
    474.                     if(followPlayer && Vector3.Distance(playerObj.transform.position, myTransform.position) > pickNextDestDist * 2f){
    475.                             speedAmt = runSpeed;
    476.                             lastRunTime = Time.time;
    477.                     }else{
    478.                         if(lastRunTime + 2.0f < Time.time){
    479.                             speedAmt = walkSpeed;
    480.                         }
    481.                     }
    482.                     TravelToPoint(playerObj.transform.position);
    483.                 }else{
    484.                     //play idle animation
    485.                     speedAmt = 0.0f;
    486.                     agent.Stop();
    487.                     SetSpeed(speedAmt);
    488.                     if(!useMecanim){
    489.                         AnimationComponent.CrossFade("idle", 0.3f);
    490.                     }else{
    491.                         if(attackFinished && attackTime < Time.time){
    492.                             AnimatorComponent.SetBool("Idle", true);
    493.                         }
    494.                         AnimatorComponent.SetBool("Walk", false);
    495.                         AnimatorComponent.SetBool("Run", false);
    496.                     }
    497.                 }
    498.             }
    499.            
    500.             yield return new WaitForSeconds(0.3f);
    501.         }
    502.        
    503.     }
    504.    
    505.     IEnumerator Patrol(){
    506.         while (true) {
    507.        
    508.             if(huntPlayer){
    509.                 SpawnNPC();
    510.                 yield break;
    511.             }
    512.            
    513.             if(curWayPoint && waypointGroup){//patrol if NPC has a current waypoint, otherwise stand watch
    514.                 Vector3 waypointPosition = curWayPoint.position;
    515.                 float waypointDist = Vector3.Distance(waypointPosition, myTransform.position);
    516.                 int waypointNumber = waypointGroup.wayPoints.IndexOf(curWayPoint);
    517.  
    518.                 //if NPC is close to a waypoint, pick the next one
    519.                 if((patrolOnce && waypointNumber == waypointGroup.wayPoints.Count - 1)){
    520.                     if(waypointDist < pickNextDestDist){
    521.                         speedAmt = 0.0f;
    522.                         startPosition = waypointPosition;
    523.                         StartCoroutine(StandWatch());
    524.                         yield break;//cancel patrol if patrolOnce var is true
    525.                     }
    526.                 }else{  
    527.                     if(waypointDist < pickNextDestDist){
    528.                         if(waypointGroup.wayPoints.Count == 1){
    529.                             speedAmt = 0.0f;
    530.                             startPosition = waypointPosition;
    531.                             StartCoroutine(StandWatch());
    532.                             yield break;//cancel patrol if NPC has reached their only waypoint
    533.                         }
    534.                         curWayPoint = PickNextWaypoint (curWayPoint, waypointNumber);
    535.                         if(spawned && Vector3.Distance(waypointPosition, myTransform.position) < pickNextDestDist){
    536.                             walkOnPatrol = true;//make spawned NPCs run to their first waypoint, but walk on the patrol
    537.                         }
    538.                     }
    539.                 }
    540.  
    541.                 //expand search radius if attacked
    542.                 if(attackedTime + 6.0f > Time.time){
    543.                     attackRangeAmt = attackRange * 6.0f;//expand enemy search radius if attacked to defend against sniping
    544.                 }else{
    545.                     attackRangeAmt = attackRange;
    546.                 }
    547.                
    548.                 //allow player to push friendly NPCs out of their way
    549.                 if(playerObj.activeInHierarchy && !collisionState && FPSWalker.capsule){
    550.                     foreach(Collider col in colliders){
    551.                         Physics.IgnoreCollision(col, FPSWalker.capsule, true);
    552.                     }
    553.                     collisionState = true;
    554.                 }
    555.  
    556.                 //determine if player is within sight of NPC
    557.                 CanSeeTarget();
    558.                 if((target && targetVisible) || heardPlayer || heardTarget){
    559.                     yield return StartCoroutine(AttackTarget());
    560.                 }else{
    561.                     if(NPCRegistryComponent){
    562.                         NPCRegistryComponent.FindClosestTarget(myTransform.gameObject, this, myTransform.position, attackRangeAmt, factionNum);
    563.                     }
    564.                     // Move towards our target
    565.                     if(attackTime < Time.time){
    566.                         if(orderedMove && !followPlayer){
    567.                             if(Vector3.Distance(startPosition, myTransform.position) > pickNextDestDist){
    568.                                 speedAmt = runSpeed;
    569.                                 TravelToPoint(startPosition);
    570.                             }else{
    571.                                 //play idle animation
    572.                                 speedAmt = 0.0f;
    573.                                 agent.Stop();
    574.                                 SetSpeed(speedAmt);
    575.                                 if(!useMecanim){
    576.                                     AnimationComponent.CrossFade("idle", 0.3f);
    577.                                 }else{
    578.                                     if(attackFinished && attackTime < Time.time){
    579.                                         AnimatorComponent.SetBool("Idle", true);
    580.                                     }
    581.                                     AnimatorComponent.SetBool("Walk", false);
    582.                                     AnimatorComponent.SetBool("Run", false);
    583.                                 }
    584.                                 StartCoroutine(StandWatch());//npc reached player-designated position, stop patrolling and wait here
    585.                                 yield break;
    586.                             }
    587.                         }else if(!orderedMove && followPlayer){
    588.                             if(Vector3.Distance(playerObj.transform.position, myTransform.position) > pickNextDestDist){
    589.                                 if(Vector3.Distance(playerObj.transform.position, myTransform.position) > pickNextDestDist * 2f){
    590.                                     speedAmt = runSpeed;
    591.                                     lastRunTime = Time.time;
    592.                                 }else{
    593.                                     if(lastRunTime + 2.0f < Time.time){
    594.                                         speedAmt = walkSpeed;
    595.                                     }
    596.                                 }
    597.                                 TravelToPoint(playerObj.transform.position);
    598.                             }else{
    599.                                 //play idle animation
    600.                                 speedAmt = 0.0f;
    601.                                 agent.Stop();
    602.                                 SetSpeed(speedAmt);
    603.                                 if(!useMecanim){
    604.                                     AnimationComponent.CrossFade("idle", 0.3f);
    605.                                 }else{
    606.                                     if(attackFinished && attackTime < Time.time){
    607.                                         AnimatorComponent.SetBool("Idle", true);
    608.                                     }
    609.                                     AnimatorComponent.SetBool("Walk", false);
    610.                                     AnimatorComponent.SetBool("Run", false);
    611.                                 }
    612.                             }
    613.                         }else{
    614.                             //determine if NPC should walk or run on patrol
    615.                             if(walkOnPatrol){speedAmt = walkSpeed;}else{speedAmt = runSpeed;}
    616.                             TravelToPoint(waypointPosition);
    617.                         }
    618.                     }
    619.                 }
    620.             }else{
    621.                 StartCoroutine(StandWatch());//don't patrol if we have no waypoints
    622.                 yield return false;
    623.             }
    624.             yield return new WaitForSeconds(0.3f);
    625.         }
    626.  
    627.     }
    628.  
    629.  
    630.     void CanSeeTarget(){
    631.    
    632.         if(spawnTime + 1f > Time.time){//add small delay before checking target visibility
    633.             return;
    634.         }
    635.        
    636.         //stop tracking target if it is deactivated
    637.         if((TargetAIComponent && !TargetAIComponent.enabled) || (target && !target.gameObject.activeInHierarchy)){
    638.             target = null;
    639.             TargetAIComponent = null;
    640.             targetVisible = false;
    641.             heardTarget = false;
    642.             return;
    643.         }
    644.  
    645.         //target player
    646.         if((factionNum != 1 || playerAttacked) && FPSWalker.capsule){
    647.  
    648.             float playerDistance = Vector3.Distance(myTransform.position + (upVec * eyeHeight), playerTransform.position + (upVec * FPSWalker.capsule.height * 0.25f));
    649.  
    650.             //listen for player attacks
    651.             if(!heardPlayer && !huntPlayer && FPSWalker.dropTime + 2.5f < Time.time){
    652.                 if(playerDistance < listenRange && (target == playerTransform || target == FPSWalker.leanObj.transform || target == null)){
    653.                     if(PlayerWeaponsComponent && PlayerWeaponsComponent.CurrentWeaponBehaviorComponent){
    654.                         WeaponBehaviorComponent = PlayerWeaponsComponent.CurrentWeaponBehaviorComponent;
    655.                         if(WeaponBehaviorComponent.shootStartTime + 2.0f > Time.time && !WeaponBehaviorComponent.silentShots){
    656.                             if(target == FPSWalker.leanObj.transform){
    657.                                 targetEyeHeight = 0.0f;
    658.                                 target = FPSWalker.leanObj.transform;
    659.                                 pursueTarget = true;
    660.                             }else{
    661.                                 targetEyeHeight = FPSWalker.capsule.height * 0.25f;
    662.                                 target = playerTransform;
    663.                             }
    664.                             timeout = Time.time + 6.0f;
    665.                             heardPlayer = true;
    666.                             return;
    667.                         }
    668.                     }
    669.                 }
    670.             }
    671.  
    672.             if(huntPlayer){
    673.                 targetEyeHeight = FPSWalker.capsule.height * 0.25f;
    674.                 target = playerTransform;
    675.             }
    676.  
    677.             if(playerDistance < attackRangeAmt){
    678.  
    679.                 //target lean collider if player is leaning around a corner
    680.                 if(Mathf.Abs(FPSWalker.leanAmt) > 0.1f
    681.                 && playerDistance > 2.0f && target == playerTransform
    682.                 && (attackedTime + 6.0f > Time.time || heardPlayer)){//allow player to peek around corners undetected if they haven't attacked this npc
    683.                     targetEyeHeight = 0.0f;
    684.                     target = FPSWalker.leanObj.transform;
    685.                 }
    686.                 //target main player object if they are not leaning
    687.                 if((Mathf.Abs(FPSWalker.leanAmt) < 0.1f || playerDistance < 2.0f) && target == FPSWalker.leanObj.transform){
    688.                     targetEyeHeight = FPSWalker.capsule.height * 0.25f;
    689.                     target = playerTransform;
    690.                 }
    691.  
    692.             }
    693.  
    694.         }
    695.  
    696.         //calculate range and LOS to target
    697.         if(target == playerTransform || target == FPSWalker.leanObj.transform || (TargetAIComponent && TargetAIComponent.enabled && target != null)){
    698.             Vector3 myPos = myTransform.position + (upVec * eyeHeight);
    699.             targetPos = target.position + (target.up * targetEyeHeight);
    700.  
    701.             targetDistance = Vector3.Distance(myPos, targetPos);
    702.             targetDirection = (targetPos - myPos).normalized;
    703.  
    704.             if(targetDistance > attackRangeAmt){
    705.                 sightBlocked = true;
    706.                 targetVisible = false;
    707.                 return;//don't continue to check LOS if target is not within attack range
    708.             }
    709.  
    710.             //check LOS with sphere casts and raycasts
    711.             if(target == playerTransform){
    712.                 hits = Physics.SphereCastAll(myPos, agent.radius * 0.35f, targetDirection, targetDistance, searchMask);
    713.             }else if(target == FPSWalker.leanObj.transform){
    714.                 hits = Physics.SphereCastAll(myPos, agent.radius * 0.1f, targetDirection, targetDistance, searchMask);
    715.             }else{
    716.                 hits = Physics.RaycastAll (myPos, targetDirection, targetDistance, searchMask);
    717.             }
    718.             sightBlocked = false;
    719.  
    720.             //detect if target is behind NPC
    721.             if(!huntPlayer
    722.             && timeout < Time.time
    723.             && attackedTime + 6.0f < Time.time
    724.             && ((target == playerTransform || target == FPSWalker.leanCol) && !heardPlayer)
    725.             && !FPSWalker.sprintActive){
    726.                 Vector3 toTarget = (targetPos - myPos).normalized;
    727.                 if(Vector3.Dot(toTarget, transform.forward) < -0.45f){
    728.                     sightBlocked = true;
    729.                     playerIsBehind = true;
    730.                     targetVisible = false;
    731.                     return;
    732.                 }
    733.             }
    734.            
    735.             playerIsBehind = false;
    736.  
    737.             //check if NPC can see their target
    738.             for(int i = 0; i < hits.Length; i++){
    739.                 if((!hits[i].transform.IsChildOf(target)//hit is not target
    740.                 && !hits[i].transform.IsChildOf(myTransform))//hit is not NPC's own colliders
    741.                 || (!playerAttacked//attack player if they attacked us (friendly fire)
    742.                     && (factionNum == 1 && target != playerObj && (hits[i].collider == FPSWalker.capsule//try not to shoot the player if we are a friendly NPC
    743.                            || hits[i].collider == FPSWalker.leanCol)))
    744.                 ){
    745.                     sightBlocked = true;
    746.                     break;
    747.                 }
    748.                 if(hits[i].transform.IsChildOf(target)){
    749.                     attackHit = hits[i];
    750.                     break;
    751.                 }
    752.             }
    753.            
    754.             if(!sightBlocked){
    755.                 if(target != FPSWalker.leanObj.transform){
    756.                     pursueTarget = false;
    757.                     targetVisible = true;
    758.                     return;
    759.                 }else{
    760.                     pursueTarget = true;//true when NPC has seen only the player leaning around a corner
    761.                     targetVisible = true;
    762.                     return;
    763.                 }
    764.             }else{
    765.                 if(TargetAIComponent && !huntPlayer){
    766.                     if(TargetAIComponent.attackTime > Time.time && Vector3.Distance(myTransform.position, target.position) < listenRange ){
    767.                         timeout = Time.time + 6.0f;
    768.                         heardTarget = true;
    769.                     }
    770.                 }
    771.                 targetVisible = false;
    772.                 return;
    773.             }
    774.            
    775.         }else{
    776.             targetVisible = false;
    777.             return;
    778.         }
    779.    
    780.     }
    781.    
    782.     IEnumerator Shoot(){
    783.  
    784.         attackFinished = false;
    785.  
    786.         // Start shoot animation
    787.         if(!useMecanim){
    788.             AnimationComponent.CrossFade("shoot", 0.3f);
    789.         }else{
    790.             AnimatorComponent.SetBool("Idle", false);
    791.             AnimatorComponent.SetBool("Walk", false);
    792.             AnimatorComponent.SetBool("Run", false);
    793.             AnimatorComponent.SetBool("Attacking", true);
    794.         }
    795.         //don't move during attack
    796.         speedAmt = 0.0f;
    797.         SetSpeed(speedAmt);
    798.         agent.Stop();
    799.  
    800.         // Wait until delayShootTime to allow part of the animation to play
    801.         yield return new WaitForSeconds(delayShootTime);
    802.         //attack
    803.         NPCAttackComponent.Fire();
    804.         if(cancelAttackTaunt){
    805.             vocalFx.Stop();
    806.         }
    807.         attackTime = Time.time + 2.0f;
    808.         // Wait for the rest of the animation to finish
    809.         if(!useMecanim){
    810.             yield return new WaitForSeconds(AnimationComponent["shoot"].length + delayShootTime + Random.Range(shotDuration, shotDuration + randShotDelay));
    811.         }else{
    812.             yield return new WaitForSeconds(delayShootTime + Random.Range(shotDuration, shotDuration + 0.75f));
    813.         }
    814.  
    815.         attackFinished = true;
    816.         if(useMecanim){
    817.             AnimatorComponent.SetBool("Attacking", false);
    818.         }
    819.  
    820.     }
    821.    
    822.     IEnumerator AttackTarget(){
    823.         while (true) {
    824.  
    825. //            navTest = agent.hasPath;
    826.  
    827. //            if(agent.pathStatus == NavMeshPathStatus.PathComplete){
    828. //                navTest = 1;
    829. //            }else if(agent.pathStatus == NavMeshPathStatus.PathPartial){
    830. //                navTest = 2;
    831. //            }else if(agent.pathStatus == NavMeshPathStatus.PathInvalid){
    832. //                navTest = 3;
    833. //            }else{
    834. //                navTest = 0;
    835. //            }
    836.        
    837.             if(Time.timeSinceLevelLoad < 1f){//add small delay before checking target visibility
    838.                 yield return new WaitForSeconds(1.0f);
    839.             }
    840.            
    841.             // no target - stop hunting
    842.             if(target == null || (TargetAIComponent && !TargetAIComponent.enabled) && !huntPlayer){
    843.                 timeout = 0.0f;
    844.                 heardPlayer = false;
    845.                 heardTarget = false;
    846.                 damaged = false;
    847.                 TargetAIComponent = null;
    848.             yield    return false;
    849.             }
    850.            
    851.             //play a taunt if hunting target
    852.             if(lastTauntTime + tauntDelay < Time.time
    853.             && Random.value < tauntChance
    854.             && (alertTaunt || alertSnds.Length <= 0)){
    855.                 if(tauntSnds.Length > 0){
    856.                     vocalFx.volume = tauntVol;
    857.                     vocalFx.pitch = Random.Range(0.94f, 1f);
    858.                     vocalFx.spatialBlend = 1.0f;
    859.                     vocalFx.clip = tauntSnds[Random.Range(0, tauntSnds.Length)];
    860.                     vocalFx.PlayOneShot(vocalFx.clip);
    861.                     lastTauntTime = Time.time;
    862.                 }
    863.             }
    864.            
    865.             //play alert sound if target detected
    866.             if(!alertTaunt){
    867.                 if(alertSnds.Length > 0){
    868.                     vocalFx.volume = alertVol;
    869.                     vocalFx.pitch = Random.Range(0.94f, 1f);
    870.                     vocalFx.spatialBlend = 1.0f;
    871.                     vocalFx.clip = alertSnds[Random.Range(0, alertSnds.Length)];
    872.                     vocalFx.PlayOneShot(vocalFx.clip);
    873.                     lastTauntTime = Time.time;
    874.                     alertTaunt = true;
    875.                 }
    876.             }
    877.            
    878.             float distance = Vector3.Distance(myTransform.position, target.position);
    879.            
    880.             if(!huntPlayer){
    881.                
    882.                 //search for player if their attacks have been heard
    883.                 if(heardPlayer && (target == playerTransform || target == FPSWalker.leanObj.transform)){
    884.                     speedAmt = runSpeed;
    885.                     SearchTarget(lastVisibleTargetPosition);
    886.                 }
    887.                 //search for target if their attacks have been heard
    888.                 if(heardTarget){
    889.                     speedAmt = runSpeed;
    890.                     SearchTarget(lastVisibleTargetPosition);
    891.                 }
    892.        
    893.                 // Target is too far away - give up  
    894.                 if(distance > attackRangeAmt){
    895.                     speedAmt = walkSpeed;
    896.                     target = null;
    897.                 yield    return false;
    898.                 }
    899.                
    900.             }else{
    901.                 target = playerTransform;
    902.                 speedAmt = runSpeed;
    903.                 TravelToPoint(target.position);
    904.             }
    905.  
    906.             if(pursueTarget){//should NPC attack player collider or leaning collider?
    907.                 lastVisibleTargetPosition = FPSWalker.leanObj.transform.position;
    908.             }else{
    909.                 lastVisibleTargetPosition = target.position + (target.up * targetEyeHeight);
    910.             }
    911.  
    912.             CanSeeTarget();
    913.             if(targetVisible){
    914.                 timeout = Time.time + 6.0f;
    915.            
    916.                 if(distance > shootRange){
    917.                     if(!huntPlayer){
    918.                         SearchTarget(lastVisibleTargetPosition);
    919.                     }
    920.                 }else{//close to target, rotate NPC to face it
    921.                     if(!turning){
    922.                         StopCoroutine("RotateTowards");
    923.                         StartCoroutine(RotateTowards(lastVisibleTargetPosition, 20.0f, 2.0f));
    924.                     }
    925.                     speedAmt = 0.0f;
    926.                     SetSpeed(speedAmt);
    927.                     agent.speed = speedAmt;
    928.                 }
    929.                
    930.                 speedAmt = runSpeed;
    931.  
    932.                 Vector3 forward = myTransform.TransformDirection(Vector3.forward);
    933.                 Vector3 targetDirection = lastVisibleTargetPosition - (myTransform.position + (myTransform.up * eyeHeight));
    934.                 targetDirection.y = 0;
    935.                
    936.                 float angle = Vector3.Angle(targetDirection, forward);
    937.                
    938.                 // Start shooting if close and player is in sight
    939.                 if(distance < shootRange && angle < shootAngle){
    940.                     if(attackFinished){
    941.                         yield return StartCoroutine(Shoot());
    942.                     }else{
    943.                         speedAmt = 0.0f;
    944.                         SetSpeed(speedAmt);
    945.                         agent.Stop();
    946.                     }
    947.                 }
    948.                
    949.             }else{
    950.                 if(!huntPlayer){
    951.                     if(attackFinished || huntPlayer){
    952.                         if(timeout > Time.time){
    953.                             speedAmt = runSpeed;
    954.                             SetSpeed(speedAmt);
    955.                             SearchTarget(lastVisibleTargetPosition);
    956.                         }else{//if timeout has elapsed and target is not visible, resume initial behavior
    957.                             heardPlayer = false;
    958.                             heardTarget = false;
    959.                             alertTaunt = false;
    960.                             speedAmt = 0.0f;
    961.                             SetSpeed(speedAmt);
    962.                             agent.Stop();
    963.                             target = null;
    964.                         yield    return false;
    965.                         }
    966.                     }
    967.                 }
    968.             }
    969.            
    970.             yield return new WaitForSeconds(0.3f);
    971.         }
    972.     }
    973.  
    974.     //look for target at a location
    975.     void SearchTarget( Vector3 position  ){
    976.         if(attackFinished){
    977.             if(target == playerTransform || target == FPSWalker.leanObj.transform || (TargetAIComponent && TargetAIComponent.enabled)){
    978.                 if(!huntPlayer){
    979.                     speedAmt = runSpeed;
    980.                     TravelToPoint(target.position);
    981.                 }
    982.             }else{
    983.                 timeout = 0.0f;
    984.                 damaged = false;
    985.             }
    986.         }
    987.     }
    988.  
    989.     //rotate to face target
    990.     public IEnumerator RotateTowards( Vector3 position, float rotationSpeed, float turnTimer, bool attacking = true ){
    991.         float turnTime;
    992.         turnTime = Time.time;
    993.  
    994.         SetSpeed(0.0f);
    995.         agent.Stop();
    996.  
    997.         while(turnTime + turnTimer > Time.time && !cancelRotate){
    998.             turning = true;
    999.  
    1000.             if(pursueTarget){
    1001.                 position = FPSWalker.leanObj.transform.position;
    1002.             }else{
    1003.                 if((target && attacking && (target == playerTransform || (TargetAIComponent && TargetAIComponent.enabled)))){
    1004.                     lastVisibleTargetPosition = target.position + (target.up * targetEyeHeight);
    1005.                 }else{
    1006.                     lastVisibleTargetPosition = position;
    1007.                 }
    1008.             }
    1009.            
    1010.             Vector3 direction = lastVisibleTargetPosition - myTransform.position;
    1011.             direction.y = 0;
    1012.             if(direction.x != 0 && direction.z != 0){
    1013.                 // Rotate towards the target
    1014.                 myTransform.rotation = Quaternion.Slerp (myTransform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    1015.                 myTransform.eulerAngles = new Vector3(0, myTransform.eulerAngles.y, 0);
    1016.                 yield return null;
    1017.             }else{
    1018.                 break;//stop rotating
    1019.             }
    1020.         }
    1021.         cancelRotate = false;
    1022.         turning = false;
    1023.     }
    1024.    
    1025.     //Allow tweaking of model yaw/facing direction from the inspector for NPC alignment with attack direction
    1026.     private IEnumerator UpdateModelYaw(){
    1027.         while(true){
    1028.            
    1029.             if(stepInterval > 0f){
    1030.                 yawAmt = Mathf.MoveTowards(yawAmt, movingYaw, Time.deltaTime * 180f);
    1031.             }else{
    1032.                 yawAmt = Mathf.MoveTowards(yawAmt, idleYaw, Time.deltaTime * 180f);
    1033.             }
    1034.  
    1035.             objectWithAnims.transform.localRotation = Quaternion.Euler(0.0f, yawAmt, 0.0f);
    1036.  
    1037.             yield return null;
    1038.         }
    1039.     }
    1040.  
    1041.     //set navmesh destination and set NPC speed
    1042.     void TravelToPoint( Vector3 position  ){
    1043.         if(attackFinished){
    1044.             agent.SetDestination(position);
    1045.             agent.Resume();
    1046.             agent.speed = speedAmt;
    1047.             SetSpeed(speedAmt);
    1048.            
    1049.         }
    1050.     }
    1051.    
    1052.     //pick the next waypoint and determine if patrol should continue forward or backward through waypoint group
    1053.     Transform PickNextWaypoint( Transform currentWaypoint, int curWaypointNumber  ){
    1054.        
    1055.         Transform waypoint = currentWaypoint;
    1056.  
    1057.         if(!countBackwards){
    1058.             if(curWaypointNumber < waypointGroup.wayPoints.Count -1){
    1059.                 waypoint = waypointGroup.wayPoints[curWaypointNumber + 1];
    1060.             }else{
    1061.                 waypoint = waypointGroup.wayPoints[curWaypointNumber - 1];
    1062.                 countBackwards = true;
    1063.             }
    1064.         }else{
    1065.             if(curWaypointNumber != 0){
    1066.                 waypoint = waypointGroup.wayPoints[curWaypointNumber - 1];
    1067.             }else{
    1068.                 waypoint = waypointGroup.wayPoints[curWaypointNumber + 1];
    1069.                 countBackwards = false;
    1070.             }
    1071.         }
    1072.         return waypoint;
    1073.     }
    1074.  
    1075.     //play animations for NPC moving state/speed and set footstep sound intervals
    1076.     void SetSpeed( float speed  ){
    1077.         if(!useMecanim){
    1078.             if (speed > walkSpeed && agent.hasPath){
    1079.                 AnimationComponent.CrossFade("run");
    1080.                 stepInterval = runStepTime;
    1081.             }else{
    1082.                 if(speed > 0.0f && agent.hasPath){
    1083.                     AnimationComponent.CrossFade("walk");
    1084.                     stepInterval = walkStepTime;
    1085.                 }else{
    1086.                     AnimationComponent.CrossFade("idle");
    1087.                     stepInterval = -1.0f;
    1088.                 }
    1089.             }
    1090.         }else{
    1091.             if (speed > walkSpeed && agent.hasPath){
    1092.                 AnimatorComponent.SetBool("Attacking", false);
    1093.                 AnimatorComponent.SetBool("Run", true);
    1094.                 AnimatorComponent.SetBool("Walk", false);
    1095.                 AnimatorComponent.SetBool("Idle", false);
    1096.                 AnimatorComponent.SetBool("Attacking", false);
    1097.                 stepInterval = runStepTime;
    1098.             }else{
    1099.                 if(speed > 0.0f && agent.hasPath){
    1100.                     AnimatorComponent.SetBool("Attacking", false);
    1101.                     AnimatorComponent.SetBool("Walk", true);
    1102.                     AnimatorComponent.SetBool("Idle", false);
    1103.                     AnimatorComponent.SetBool("Run", false);
    1104.                     AnimatorComponent.SetBool("Attacking", false);
    1105.                     stepInterval = walkStepTime;
    1106.                 }else{
    1107.                     if(attackFinished && attackTime < Time.time){
    1108.                         AnimatorComponent.SetBool("Idle", true);
    1109.                         AnimatorComponent.SetBool("Attacking", false);
    1110.                     }else{
    1111.                         AnimatorComponent.SetBool("Idle", false);
    1112.                     }
    1113.                     AnimatorComponent.SetBool("Walk", false);
    1114.                     AnimatorComponent.SetBool("Run", false);
    1115.                     stepInterval = -1.0f;
    1116.                 }
    1117.             }
    1118.         }
    1119.     }
    1120.  
    1121.     IEnumerator PlayFootSteps(){
    1122.         while(true){
    1123.             if(footSteps.Length > 0 && stepInterval > 0.0f ){
    1124.                 footstepsFx.pitch = 1.0f;
    1125.                 footstepsFx.volume = footStepVol;
    1126.                 footstepsFx.clip = footSteps[Random.Range(0, footSteps.Length)];
    1127.                 footstepsFx.PlayOneShot(footstepsFx.clip);
    1128.             }
    1129.             yield return new WaitForSeconds(stepInterval);
    1130.         }
    1131.     }
    1132.    
    1133.     //Interact with NPC when pressing use key over them
    1134.     public void CommandNPC () {
    1135.         if(factionNum == 1 && followOnUse && commandedTime + 0.5f < Time.time){
    1136.             orderedMove = false;
    1137.             cancelRotate = false;
    1138.             commandedTime = Time.time;
    1139.             if(attackFinished && !turning){
    1140.                 StopCoroutine("RotateTowards");
    1141.                 StartCoroutine(RotateTowards(playerTransform.position, 10.0f, 2.0f, false));
    1142.             }
    1143.             if(!followPlayer){
    1144.                 if((followFx1 || followFx2) && ((jokeFx && jokePlaying + jokeFx.length < Time.time) || !jokeFx)){
    1145.                     if(Random.value > 0.5f){
    1146.                         vocalFx.clip = followFx1;
    1147.                     }else{
    1148.                         vocalFx.clip = followFx2;
    1149.                     }
    1150.                     vocalFx.pitch = Random.Range(0.94f, 1f);
    1151.                     vocalFx.spatialBlend = 1.0f;
    1152.                     vocalFx.PlayOneShot(vocalFx.clip);
    1153.                 }
    1154.                 followPlayer = true;
    1155.             }else{
    1156.                 if((stayFx1 || stayFx2) && ((jokeFx && jokePlaying + jokeFx.length < Time.time) || !jokeFx)){
    1157.                     if(Random.value > 0.5f){
    1158.                         vocalFx.clip = stayFx1;
    1159.                     }else{
    1160.                         vocalFx.clip = stayFx2;
    1161.                     }
    1162.                     vocalFx.pitch = Random.Range(0.94f, 1f);
    1163.                     vocalFx.spatialBlend = 1.0f;
    1164.                     vocalFx.PlayOneShot(vocalFx.clip);
    1165.                 }
    1166.                 startPosition = myTransform.position;
    1167.                 followPlayer = false;
    1168.             }
    1169.         }
    1170.         if(jokeFx && factionNum == 1 && followOnUse){
    1171.             if(jokeCount == 0){
    1172.                 talkedTime = Time.time;
    1173.             }
    1174.             if(talkedTime + 0.5f > Time.time){
    1175.                 talkedTime = Time.time;
    1176.                 jokeCount++;
    1177.                 if(jokeCount > jokeActivate){
    1178.                     if(!jokeFx2){
    1179.                         vocalFx.clip = jokeFx;
    1180.                     }else{
    1181.                         if(Random.value > 0.5f){
    1182.                             vocalFx.clip = jokeFx;
    1183.                         }else{
    1184.                             vocalFx.clip = jokeFx2;
    1185.                         }
    1186.                     }
    1187.                     vocalFx.pitch = Random.Range(0.94f, 1f);
    1188.                     vocalFx.spatialBlend = 1.0f;
    1189.                     vocalFx.PlayOneShot(vocalFx.clip);
    1190.                     jokePlaying = Time.time;
    1191.                     jokeCount = 0;
    1192.                 }
    1193.             }else{
    1194.                 jokeCount = 0;
    1195.             }
    1196.         }
    1197.     }
    1198.    
    1199.     //Move an NPC to a specific position
    1200.     public void GoToPosition (Vector3 position, bool runToPos) {
    1201.         if(runToPos){
    1202.             orderedMove = true;
    1203.         }else{
    1204.             orderedMove = false;
    1205.         }
    1206.         cancelRotate = true;
    1207.         startPosition = position;
    1208.     }
    1209.  
    1210. //    //used to change the faction of the NPC
    1211.     public void ChangeFaction(int factionChange){
    1212.         target = null;
    1213.         factionNum = factionChange;
    1214.     }
    1215.  
    1216. }
     
  36. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299

    Yes, it's just how the "new" yield expression is now used in Unity's C#. Glad you figured it out, nice to see some members brave enough to dig a bit into the code, for their custom solutions needed :). :cool:
     
    Last edited: Mar 19, 2019
  37. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299

    Try keeping the resources / scripts that do the underwater effects in a more "official" named Unity folders, so they get included into the build, I will try that first, to see what happens ... Also try your backup version of the RFPS player you have made earlier (haven't you ?), on a different map, and just terrain and that version of water you have, to learn more :).
     
  38. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260
    Hey Tony Li! Got some questions for you on the save system. (I just noticed it was updated today and that it will fix an error I have been seeing, but haven't had a chance to track down yet! ya>)

    1) So first off. none of my FPS_main inventory is coming along for the scene change. no weapons or ammo or positioning (but oddly enough the scene transition happens great, except for those issues) Not sure what I did wrong there.

    2) I want to get the standard scene transition manager working. I want a slight fade out on hitting a scene portal and I suspect this may be the way to go,(is it in your opinion?) I don't really want to start moding your code to add courutines and the like to get the fade out and I am hoping I can get the scene fade out through the transition manager.

    3) is there any way to tell what version of save system I have loaded in unity? I suspect I am a few versions behind, but want to make sure before I go a ripping out code.


    Thanks in advance mate!
     
  39. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    Check these:
    • FPS Player has an FPS Player Saver component.
    • Save Across Scene Changes is ticked.
    • Its key is unique within the scene (i.e., no other savers are using the same key), but is the same key as FPS Player Saver components in all scenes.
    If that checks out, are there any errors or warnings in the Console window or output log file?

    That's exactly what the scene transition manager is for. No need for any coding.
    1. Add a Scene Transition Manager component to the Save System GameObject.
    2. Add a Canvas as a child of the Save System. Set its Sort Order to 9999 so it's on top of everything.
    3. Add an Image that covers the whole screen.
    4. Create an animator controller and animations that enable/disable the Image and fade its alpha value.
    5. Assign the animator controller to an Animator.
    6. Assign the Animator to the Scene Transition Manager. Set the Leave Scene > Trigger and Animation Duration.
    If you have a copy of the Dialogue System, to save some steps you can grab its SceneFaderCanvas prefab and related animations. The Dialogue System and the Save System for RFPSP use the same Scene Transition Manager.

    It's in Pixel Crushers / Save System for RFPSP / _RELEASE_NOTES.txt.
     
    Weblox and SickaGames1 like this.
  40. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260
    ;-)


    Humm my reply got mangled in there somewhere
     
    Last edited: Mar 20, 2019
    SickaGames1 likes this.
  41. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,697
    FPS_Main / FPS Player isn't a persistent singleton. Each scene should have its own instance, and each instance's FPS Player should have an FPS Player Saver.

    As long as there isn't another saver on FPS Player, it will use the GameObject name ("FPS Player") as the key, so that's fine. If you add another saver component, then you'll want to specify keys.

    Yup, the evaluation version has the same prefab. Good thinking.
     
  42. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260


    FPS_Main / FPS Player isn't a persistent singleton. Each scene should have its own instance, and each instance's FPS Player should have an FPS Player Saver.

    Ahhhh I bet this is the culprit! I only have it on the first one. oddly enough it does save the game where I left off though.... You 'd man!
     
  43. Mario167100

    Mario167100

    Joined:
    Jul 25, 2016
    Posts:
    49
    With the changes made to Unity, you can't delete assets within a prefab unless you open the prefab. I just wanted to know how this would change our ability to create our own custom weapons in RFPS.
     
  44. jons190

    jons190

    Joined:
    Sep 13, 2016
    Posts:
    260
    Not sure. I'm on unity 2018 and not sure I've noticed that behavior.
     
  45. SickaGames1

    SickaGames1

    Joined:
    Jan 15, 2018
    Posts:
    1,270
    How do u set up a sword and a shield?
     
  46. Mario167100

    Mario167100

    Joined:
    Jul 25, 2016
    Posts:
    49
    Which version of 2018?
     
  47. Team_Resurrection

    Team_Resurrection

    Joined:
    Nov 24, 2016
    Posts:
    3
    For anyone still using rfps 1.2.3 can you help me on how to change the health system to glitch the screen out more and more the more damage taken similar to this?

    If you can help please message me or something, I may be able to pay for help.
     
    OZAV likes this.
  48. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299

    ... our advice here is that: every deprecated asset on the store, you (as the purchasers) are still able to download in your store dashboard, for your own uses, any time later, so you can always go back to it that way, if you need, at any time. That's one good thing to know, as we can see that many people don't know it. That last version is the last official one, even if is deprecated, and is available that way, for the future, and so far - Unity keeps all those deprecated versions on the store without removing them, which is well done on their part, so: "deprecated' means only: unsupported currently and does not mean copyright free, and does not mean unavailable, and does not mean any harmful ideas that people with no brain or asset flippers, or negative minded people can imagine or suggest either, but is still and permanently available - that way, for all who purchased it, and is still the valid and last updated, and last official version, for every deprecated asset, that particular way. So, now - the such better understanding of what 'deprecated' means will also help to stop spreading negative agendas around community, which does not help, and we should all stay away from, since Unity (always was, always will) is a - community first. If the asset has a good quality and (quality) community members, as we have here, it can practically live forever, no matter the dev's input or not, and this is what we have here, and we would like to keep it that way, for the future and the returning users, always with something nice to contribute here, about the asset uses. That is the main signature of the members here so far, and we have it argumented for long enough, as well, so we will keep our input - to stay always constructive (and active), which we also advise to everyone here, same as well. The only quality is (and it should be) in the quality of the members and not much of any particular asset itself that much :).
     
  49. OZAV

    OZAV

    Joined:
    Aug 9, 2013
    Posts:
    299

    ... disagree ... Unity should not remove deprecated assets form the servers, it's very important they stay available for the later uses of the purchasers, and the community itself. What you are suggesting here is not constructive, so please stay away form spreading such, or any negative ideas around this forum, where we (for the difference from the other forums around) do not welcome such negative agendas. The only quality is (and it should be) in the quality of the members and not much of any particular asset itself, thanks for your understanding.
     
    Last edited: Mar 24, 2019
  50. TheMessyCoder

    TheMessyCoder

    Joined:
    Feb 13, 2017
    Posts:
    522
    It is perfectly acceptable to disagree, thats what mature and sensible human beings can do. However do not instruct people to stay away from voicing their opinions because you disagree with it. Make your case for why you believe that persons opinion is wrong and engage them in a conversation. I have no agenda, I am a consumer with an opinion.

    If you have purchased an asset you still have it available to download even if its deprecated. So what you have said is not technically correct. My suggestion only stops new people purchasing an asset which would prevent them from downloading an asset which is not supported.

    Someone who purchased an asset and received active customer support pays the same price as someone who purchases an asset and does not receive customer support is not acceptable. This is not directed only at this asset but any asset that no longer has the resources or capacity to support its product.

    I had been contacted by people to ask me if this asset was dead long before it was deprecated. People saying that they didnt get replies from the developers and if it was being updated.

    Having the community support in place of the official support is nice of the community but should not replace a developers obligation to support an asset.

    Assets are not required to be constantly updated by a developer, if a developer releases an asset which they feel is feature complete then that is perfectly acceptable, even if they wish to not update the asset to support never versions of unity. Stating clearly that it is only compatible with versions, X, Y or Z. Bugs in those officially supported versions do need to be resolved however if they are preventing the core functionality of working. Again, not directed at this asset, but thats for products in general.

    Now if an asset is feature complete, bug free but still does not provide customer support then it should be deprecated.
    Again, to be clear, if you purchased the asset and its deprecated you can still download it from your unity account


    I honestly have no idea what this means.
     
    JBR-games likes this.