thehawk
New Member
Posts: 4
Posts: 4
|
Post by thehawk on Dec 5, 2016 2:04:02 GMT
|
|
|
Post by DarkTonic Dev on Dec 5, 2016 5:14:37 GMT
Extremely cool! Thanks for posting.
|
|
|
Post by baroquedub on Dec 22, 2016 16:30:16 GMT
This is such a great share, thank you so much for taking the time to post this (complete with all of the code changes on your blog). Have a drink on me! A couple of things caught me out at first, which others might want to know... - you obviously need to make sure that the Tactical AI demo is working before trying this integration (i.e. add 'level Parts' on layer 8) - that additional Team 1_Shotgun prefab in the MixedEnemies prefab pool also needs the new TacticalAIRagdollDespawner.cs script on its ragdoll Would be brilliant if you developed this into a longer tutorial series - maybe explaining how you're setting up your waves and using WorldVariables to develop a proper game? (I'm new to CoreGameKit and I'm find the video tutorials a bit confusing at times, more showing the features rather than real-world implementation within a game) Similarly, guidance on integrating UFPS would be brilliant (The Tactical AI documentation on the subject is very brief) Now maybe DarkTonic and squared55 can get together to provide an integration package that will mean that all these code changes don't break whenever either of them updates their asset
|
|
|
Post by baroquedub on Dec 22, 2016 17:19:07 GMT
ps. Quick question...
So I'm finding that after the AI Agents die, their parent prefab(s) remains active in CGK's PoolBoss for between 30-60 seconds. This means that after the wave ends there's a long delay before new enemies are spawned again. If I understand things correctly it's not until they've been deactivated that you get the next wave (or the wave repeat).
Is there a way of making this delay shorter?
I'm looking at your TacticalAIRagdollDespawner.cs script and it looks like the AIDeathGo coroutine should be despawning the ragdoll's parent as soon as it's called; it calls the method: PoolBoss.Despawn(myParent); but they definitely don't despawn (I've checked in the PoolBoss inspector) and I've added a debug statement in the method in PoolBoss.cs:
public static void Despawn(Transform transToDespawn) {
Debug.Log("Despawn called on "+transToDespawn.name); and that doesn't get called until the 60-30second delay after death has occurred.
Is this a CoreGameKit issue? Is there some setting I'm missing?
|
|
|
Post by baroquedub on Dec 22, 2016 18:19:45 GMT
Never mind, I'll answer my own question since I've worked it out after a bit of detective work, and thanks to RedHawk's very well document script modifications This is a tactical AI setting: TacticalAIRagdollDespawner.cs does exactly what it's told; Now to find out how to despawn (i.e. deactivate the parent) but still allow a delay before the ragdoll is deinstantiated...
|
|
|
Post by DarkTonic Dev on Dec 22, 2016 20:48:38 GMT
Re: your first post, possible but there's a lot more on the roadmap ahead of your request unfortunately.
We don't use UFPS either, so that puts it smack at the bottom of the roadmap if I had to place it.
|
|
|
Post by baroquedub on Dec 22, 2016 22:03:57 GMT
So here's my mod for leaving bodies on the battlefield while allowing instant despawning. This allows waves to restart quickly but looks more realistic than having TimeUntilBodyIsDestroyed set to zero. disclaimer (!) I'm learning by going through RedHawk's code - so not only may I have got the wrong end of the stick and got things wrong, but the credit is entirely his! so.. 1. create a copy of the Soldier_Ragdoll (Take a Tactical AI agent, break the prefab Instance, remove Soldier_Ragdoll from it's parent, and delete the parent) 2. create a new prefab from this copy of Soldier_Ragdoll. I named this 'Soldier_Dead' 3. remove the animator on the prefab 4. add a Core Gamekit TimedDespawner (time doesn't matter as it will be adjusted programmatically, but tick start on awake) 5. starting with the Pelvis (and do all of its children that have them) remove the HitBox script (it's no longer needed) and set the Rigibody to non kinematic (i.e. untick isKinematic) 6. add your 'Soldier_Dead' prefab to the pool Now in BaseScript.cs line 815 (in the KillAI() method) slightly change RedHawk's original script: // JDP for CoreGameKit Transform body = PoolBoss.SpawnOutsidePool("Soldier_Dead",this.transform.position,this.transform.rotation); // spawn a dead body body.GetComponent<TimedDespawner>().ChangeTimerDelay(timeUntilBodyIsDestroyedAfterDeath); // set auto despawn time animationScript.myAIBodyTransform.gameObject.SendMessage("AIDeath",SendMessageOptions.DontRequireReceiver); // no longer needs to pass the delay time animationScript.myAIBodyTransform.gameObject.SendMessage("SetParent",this.gameObject.transform,SendMessageOptions.DontRequireReceiver); myTargetScript.RemoveThisTargetFromPLay(); animationScript.enabled = false; This spawns a dead body at the place of death and auto despawns it depending on the time chosen on the Tactical AI agent. As the 'timeUntilBodyIsDestroyedAfterDeath' delay is no longer needed, TacticalAIRagdollDespawner.cs can be simplified: using UnityEngine; using System.Collections; using System.Collections.Generic; using DarkTonic.CoreGameKit; using TacticalAI;
public class TacticalAIRagdollDespawner : MonoBehaviour {
Transform myParent=null;
//This function is called by TacticalAI.BaseScript public void AIDeath(){ StartCoroutine("AIDeathGo"); }
//This function is called by TacticalAI.BaseScript public void SetParent(Transform parentTransform){
myParent=parentTransform;
}
IEnumerator AIDeathGo ()
{
yield return null; // this seems necessary (otherwise parent can be null) myParent.position = Vector3.zero; myParent.rotation = Quaternion.identity; this.transform.SetParent(myParent); this.transform.position = Vector3.zero; this.transform.rotation = Quaternion.identity; PoolBoss.Despawn(myParent);
}
// old ragdoll reset is now in new TacticalAIRagdollResetter.cs
} and finally (as you'll see by the code comment above), create a new script called TacticalAIRagdollResetter.cs : using UnityEngine; using System.Collections; using System.Collections.Generic; using DarkTonic.CoreGameKit;
public class TacticalAIRagdollResetter : MonoBehaviour {
void OnStart() { SaveRagdollStart(); }
// void OnSpawned(){ // ResetRagdoll(); // not sure if this is best done here, rather than in OnDespawned? // }
void OnDespawned() {
this.transform.position = Vector3.zero; this.transform.rotation = Quaternion.identity; ResetRagdoll(); // NB. putting this here allows us to remove line 84 in AnimationScript.cs (OnSpawned() method)
}
// Below as is same as the original TacticalAIRagdollDespawner.cs
/// <summary> /// Initialize the Ragdoll by getting all the components and resetting the Ragdoll on each Start/Spawn /// </summary>
Dictionary<Transform, Quaternion> TransformRotations = new Dictionary<Transform, Quaternion>(); Dictionary<Transform, Vector3> TransformPositions = new Dictionary<Transform, Vector3>(); protected List<Transform> m_Transforms = null; protected List<Rigidbody> m_Rigidbodies = null; Quaternion m_Rot; Vector3 m_Pos;
protected List<Transform> Transforms
{
get { if (m_Transforms == null) { m_Transforms = new List<Transform>(); foreach (Rigidbody r in Rigidbodies) { m_Transforms.Add(r.transform); } } return m_Transforms; } }
protected List<Rigidbody> Rigidbodies { get { if (m_Rigidbodies == null) m_Rigidbodies = new List<Rigidbody>(GetComponentsInChildren<Rigidbody>()); return m_Rigidbodies; } }
//Function saves the start position of the Ragdoll void Start() { SaveRagdollStart(); }
private void SaveRagdollStart() { foreach (Transform t in Transforms) { if (!TransformRotations.ContainsKey(t)) TransformRotations.Add(t.transform, t.localRotation); if (!TransformPositions.ContainsKey(t)) TransformPositions.Add(t.transform, t.localPosition); } }
//Function resets the ragdoll to the start position private void ResetRagdoll() { foreach (Transform t in Transforms) { if (TransformRotations.TryGetValue(t, out m_Rot)) t.localRotation = m_Rot; if (TransformPositions.TryGetValue(t, out m_Pos)) t.localPosition = m_Pos; } } }
The above, does the same resetting of the ragdoll as RedHawk's original script, but moves the reset to OnDespawned() Now add this script to all ragdolls - the new prefab you created in the steps above (Soldier_Dead), but also all of the pooling agents' ragdoll (this is in addition to the despawner). When you're done you should have something a bit like this:
|
|
|
Post by baroquedub on Dec 22, 2016 22:06:50 GMT
Re: your first post, possible but there's a lot more on the roadmap ahead of your request unfortunately. We don't use UFPS either, so that puts it smack at the bottom of the roadmap if I had to place it. No worries, but this integration would be more with Tactical Shooter AI (squared55's asset) rather than UFPS. Although that would be nice too
|
|
|
Post by DarkTonic Dev on Dec 23, 2016 2:25:09 GMT
Re: your first post, possible but there's a lot more on the roadmap ahead of your request unfortunately. We don't use UFPS either, so that puts it smack at the bottom of the roadmap if I had to place it. No worries, but this integration would be more with Tactical Shooter AI (squared55's asset) rather than UFPS. Although that would be nice too You might instead ask squared55 if he wants to include Core GameKit integration. But I know from experience that "integration" which involves replacing certain code files with modified versions can be a maintenance nightmare... it may be more ok for them since it's their code that's being modified, not sure.
|
|
|
Post by baroquedub on Dec 23, 2016 2:48:40 GMT
You're right, of course. Thanks as always.
|
|
|
Post by DarkTonic Dev on Dec 23, 2016 6:21:56 GMT
No problem. Post back here with your thoughts any time!
|
|
|
Post by baroquedub on Jan 4, 2017 23:55:45 GMT
For anyone following this mod, and wondering why the AI no longer attack non-spawned GameObjects with the TargetScript.cs on them (most importantly the Player)... turns out that there's a problem with the way RedHawk has moved that script's functionality from Awake() and Start() to OnSpawned(). I found that you need to reinstate those commented out methods so that non-spawned objects also get added to the Targets list. An easy way is to add a public bool: public bool aSpawnedAgent = true; then either use the onSpawned code or Awake/Start depending on this variable's state: void OnSpawned()
{
if(aSpawnedAgent == false)
return; // bail out
// continue as before... and void Awake()
{
if(aSpawnedAgent == true)
return; // bail out
// continue as before.. void Start()
{
if(aSpawnedAgent == true)
return; // bail out
// continue as before.. The slight problem is that you won't see a tick box in the inspector for this public bool until you alter TargetScriptInspector.cs (in TacticalShooterAi/Editor/ParagonAI_EditorScripts/CustomInspectors/) I don't know that much about creating custom inspectors but I just copied all the code entries for the variable above (canAcceptDynamicObjectRequestsProp) and replaced with the new variable name. Works great.
|
|
|
Post by DarkTonic Dev on Jan 5, 2017 0:49:18 GMT
Thanks for the update!
|
|
thehawk
New Member
Posts: 4
Posts: 4
|
Post by thehawk on Jan 5, 2017 15:38:57 GMT
For anyone following this mod, and wondering why the AI no longer attack non-spawned GameObjects with the TargetScript.cs on them (most importantly the Player)... turns out that there's a problem with the way RedHawk has moved that script's functionality from Awake() and Start() to OnSpawned(). I found that you need to reinstate those commented out methods so that non-spawned objects also get added to the Targets list. An easy way is to add a public bool: public bool aSpawnedAgent = true; then either use the onSpawned code or Awake/Start depending on this variable's state: void OnSpawned()
{
if(aSpawnedAgent == false)
return; // bail out
// continue as before... and void Awake()
{
if(aSpawnedAgent == true)
return; // bail out
// continue as before.. void Start()
{
if(aSpawnedAgent == true)
return; // bail out
// continue as before.. The slight problem is that you won't see a tick box in the inspector for this public bool until you alter TargetScriptInspector.cs (in TacticalShooterAi/Editor/ParagonAI_EditorScripts/CustomInspectors/) I don't know that much about creating custom inspectors but I just copied all the code entries for the variable above (canAcceptDynamicObjectRequestsProp) and replaced with the new variable name. Works great. Not sure I'm following. Every time something is spawned that has the Target script it's added to the list of targets. It looks like you are manually setting the boolean value in the editor only and not in code. Any chance you could clarify so I could update my edited script.
|
|
|
Post by baroquedub on Jan 5, 2017 15:45:40 GMT
The original version works great for anything that's spawned (and has the Target script on it) but I was finding that these spawned agents only attacked each other and not my player (which also has a target script on it, but isn't spawned)
Using my slight modification I can untick the boolean to false on my player (or any other non-spawned object) and also allow it to be attacked.
and yes, you could set it programmatically and bypass having to modified the custom inspector script.
Thanks again for the epic share. Been having a lot of fun with it.
|
|