About Die and Block ability for AI agent

wuyan

Member
Hello, I tried to add Die ability and Block ability to AI agent. But I encountered a bit of confusion.

1, I want to activate Die Abiltiy based on the weapon that kills the character.This is because ,can't use the same group of die animations for all situation, such as being blown up by a bomb, burned by fire, or killed by a sword.So how do I do that?

2, I try to add block ability to AI agent. I add shield component and shield collider component to the sword in AI hand. But it didn't seem to work. I successfully added this ability to the character controlled by the player in the same way. But the difference is that the player character integrates UIS, while the AI character does not. So what could be the problem?

Thanks!!
 
1. This page describes how to subclass the Die ability to set the DeathTypeIndex, to allow different death type animations. You can use the OnObjectImpact event used by MeleeWeapon, ShootableWeapon and Projectiles (example for MeleeWeapon on this page, under "Impact Callback") to determine the item object that attacked. You'd then need to simply set the DeathTypeIndex in the Die ability based on the most recent attacker object.

2. Which part of the shield setup is not working? Does the attacker collide with the shield at all? Does the damage apply without being absorbed?
 
1. This page describes how to subclass the Die ability to set the DeathTypeIndex, to allow different death type animations. You can use the OnObjectImpact event used by MeleeWeapon, ShootableWeapon and Projectiles (example for MeleeWeapon on this page, under "Impact Callback") to determine the item object that attacked. You'd then need to simply set the DeathTypeIndex in the Die ability based on the most recent attacker object.

2. Which part of the shield setup is not working? Does the attacker collide with the shield at all? Does the damage apply without being absorbed?
Hi Andrew, Thank you!

1, As a test, I added the following code(marked bold) directly to die.cs. But I didn't get the contents of debug. log. This seems to be because the colliders that detect damage are all on the character's sub objects. OnobjectImpact event doesn't seem to listen for colliders impact on sub objects. Is that right? Or did I make mistake? What should i do?

public override void Awake()
{
base.Awake();
EventHandler.RegisterEvent<Vector3, Vector3, GameObject>(m_GameObject, "OnDeath", OnDeath);
EventHandler.RegisterEvent(m_GameObject, "OnRespawn", OnRespawn);

EventHandler.RegisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(m_GameObject, "OnObjectImpact", OnImpact);
}

private void OnImpact(float amount, Vector3 position, Vector3 forceDirection, GameObject attacker, object attackerObject, Collider hitCollider)
{
Debug.Log(m_GameObject.gameObject.name + " impacted by " + attacker +"And "+ attackerObject + " on collider " + hitCollider + ".");
}


2, AI fights with the character I control. Shield components are added to the swords of both sides. When AI aim, I attack him with sword, my sword collides with his sword's box collider. Shield did not absorb damage. AI does not activate block ability and still receive damage.In contrast, when I aim, AI attacks me, everything work well.

It should be noted that the sword used by the character I control is integrated with UIS and can be picked up.AI uses no integrated UIS and no Pickup sword.When I was using Character Manager to add the shied action to the AI sword, I didn't successfully add the Shield Collider component. I added it manually.So I'm not sure if there's something wrong here?
 
Last edited:
1. You can listen for the OnImpact event on the character object, even if the colliders are on child objects. I'm not sure if listening for that event in the Die script will work as you expect. Have you tried creating a blank script and listening for the event in that? If you're not getting any results that way, then the hit may not be getting detected at all.

2. The ShieldCollider component should be fine, as long as it's attached to the same object with the collider. (Also make sure that object is on the right layer.) Aso make sure "require aim" is disabled on the AI character's Shield. If that doesn't help, you can start debug logging in Shield.Damage to see if the damage is being received and where it's getting cut off.
 
1. You can listen for the OnImpact event on the character object, even if the colliders are on child objects. I'm not sure if listening for that event in the Die script will work as you expect. Have you tried creating a blank script and listening for the event in that? If you're not getting any results that way, then the hit may not be getting detected at all.

2. The ShieldCollider component should be fine, as long as it's attached to the same object with the collider. (Also make sure that object is on the right layer.) Aso make sure "require aim" is disabled on the AI character's Shield. If that doesn't help, you can start debug logging in Shield.Damage to see if the damage is being received and where it's getting cut off.
1,I used a blank script to add on the AI.The code is as follows.The result is the same, I can do damage to him every time I attack, but I can't get the contents of debug.log.The reason I asked you that yesterday is that if I add a capsule Collider component directly on AI, most of the time I can get the contents of the debug.log.

public class test : MonoBehaviour
{
void Awake()
{
EventHandler.RegisterEvent<float, Vector3, Vector3, GameObject, object, Collider>(gameObject, "OnObjectImpact", OnImpact);
}

private void OnImpact(float amount, Vector3 position, Vector3 forceDirection, GameObject attacker, object attackerObject, Collider hitCollider)
{
Debug.Log("WWWYYY" + gameObject + " impacted by " + attacker + "And " + attackerObject + " on collider " + hitCollider + " " + amount);
}

2, When I increase the scale of shield collider, the problem has been solved.
 
Last edited:
In that case the problem is probably that the collision is not happening at all, e.g. the weapon could be colliding with something that's in the way first. If the AI is holding a shield, then the character's weapon could be colliding with the shield's collider first, which I believe OnImpact won't listen for as it's part of a separate transform hierarchy. To test this you could put your OnImpact script onto the shield collider object. Also make sure to check the layers of the AI's colliders, that they are on layers that the character's weapon can collide with.
 
In that case the problem is probably that the collision is not happening at all, e.g. the weapon could be colliding with something that's in the way first. If the AI is holding a shield, then the character's weapon could be colliding with the shield's collider first, which I believe OnImpact won't listen for as it's part of a separate transform hierarchy. To test this you could put your OnImpact script onto the shield collider object. Also make sure to check the layers of the AI's colliders, that they are on layers that the character's weapon can collide with.
I've tested it, just like I said before. If I add the test component directly to the shield. I can get the debug content. If add the test component to the parent of shield, such as item, hand. will not get the debug content. If add the test component to AI Character, and delete the shield on the AI hand and leave the AI hand empty. I still can't get the debug content. If I add test components to the AI's sub objects which have a collider , such as head and chest, as long as my sword cuts there, I will get the debug content.

Besides, I don't understand what you mean by "part of a separate transform hierarchy"? The shield held by AI is still a sub object of the AI, isn't it?

So I think as I said before, onimpact doesn't seem to be able to effectively monitor collisions on sub objects. Because I can do damage to the AI every attack. This shows that there is no problem with the collisions. The problem is that the onimpact event doesn't work as we expect or want.

I now need an effective way to know characters be killed by which type of weapon. Many games also need to know which weapon the character is hurt by. For example, rifles, swords, grenades, bows and arrows, falls, car crashes and so on. So could you please check that if anywhere of onimpact event can be improved . Or is there any other good way to get which weapon does damage to a character. Thank you so much!
 
Sorry, I see what you mean now, I was thinking of global events.

If having the OnImpact script directly to the item colliders isn't an option, then another approach would be to have a custom script on your base character object which would automatically add that script to any relevant collider objects. In this case, that would mean getting a reference to the shield item itself, then getting the visible shield gameobject from its First/ThirdPersonPerspectiveItem component (e.g. FirstPersonPerspectiveItem.Object), and using AddComponent on that gameobject. You could do some/all of the process of getting the references automatically in code or by using publics in the inspector, depending on what suits your case best.
 
Sorry, I see what you mean now, I was thinking of global events.

If having the OnImpact script directly to the item colliders isn't an option, then another approach would be to have a custom script on your base character object which would automatically add that script to any relevant collider objects. In this case, that would mean getting a reference to the shield item itself, then getting the visible shield gameobject from its First/ThirdPersonPerspectiveItem component (e.g. FirstPersonPerspectiveItem.Object), and using AddComponent on that gameobject. You could do some/all of the process of getting the references automatically in code or by using publics in the inspector, depending on what suits your case best.
Hi,
I don't think this method is appropriate. First of all there's probability that it can be detected using this method., but not every time. I guess the way to detect Hitbox damage is different from that of onimpact. Secondly, damage judgment and attack weapon judgment use different methods in two different places, which is not rigorous. There may be inaccuracies.

A more appropriate method may be to add an attack weapon Item definition parameter to the ondamage event(Or at least one enum, ShootableWeapon, MeleeWeapon, Destructible, implosion, Fall, others.). As I said earlier, many games need to know what weapons a character is hurt by. I also checked the calls of Health.Damage(). If I modify the source code directly, I need to modify several places, and every time you update, Those will be overridden. Development will be cumbersome. If there is no other better way, I think adding this parameter is simple, effective and worthwhile.

I hope you can think about it!!!!

Thank you so much!!!!
 
Last edited:
Since there's no way in Unity to detect collisions on other gameobjects (i.e. OnTriggerEnter, OnCollisionEnter etc. use the gameobject's own colliders only) there's no other easy way around this.

The attackerObject parameter will usually be able to do what you're describing, e.g. if the attacker is using a sword then attackerObject will be the sword object, or if it was a projectile then it will be the projectile object itself. There are cases where an impact can occur from other sources than just a character, so it may not always be possible to send info like the item that was used (and as I said the attackerObject fills this purpose anyway). I'll pass on the suggestion though, thanks.
 
Since there's no way in Unity to detect collisions on other gameobjects (i.e. OnTriggerEnter, OnCollisionEnter etc. use the gameobject's own colliders only) there's no other easy way around this.

The attackerObject parameter will usually be able to do what you're describing, e.g. if the attacker is using a sword then attackerObject will be the sword object, or if it was a projectile then it will be the projectile object itself. There are cases where an impact can occur from other sources than just a character, so it may not always be possible to send info like the item that was used (and as I said the attackerObject fills this purpose anyway). I'll pass on the suggestion though, thanks.
Yes, I've considered the way that weapon used by the attacker. As you said,this is not feasible. For example, the attacker holds a sword, but the damage is caused by the grenade he threw before. Thank you so much for passing on this suggestion. Because I need this in my current work, I will add this parameter temporarily so that my current work can continue. I look forward to your official updates.

In addition, I often have to make small changes to the source code, such as making a private method or property public so that can be called elsewhere. But if I do, every time you update, it will be overridden. The further I go, the more I need to handle it manually every update. Do you have any better suggestions?
 
Last edited:
For editing source code, 2 suggestions are:

1. Use subclassing and overrides wherever possible
2. When you have to edit source code, wrap your changes in comments, then whenever you update UCC you can simply search for those comments and copy over your changes to the new files, e.g.

C#:
void SomeSourceMethod() {
    ...
    // @mychanges start
    myCustomCode();
    // @mychanges end
    ...
}

then you'd just search your codebase for @mychanges
 
For editing source code, 2 suggestions are:

1. Use subclassing and overrides wherever possible
2. When you have to edit source code, wrap your changes in comments, then whenever you update UCC you can simply search for those comments and copy over your changes to the new files, e.g.

C#:
void SomeSourceMethod() {
    ...
    // @mychanges start
    myCustomCode();
    // @mychanges end
    ...
}

then you'd just search your codebase for @mychanges
Thank you!
 
Top