Magic projectile collision force hits enemy towards me instead of away.

zoicelols

Member
Magic projectile collision forces the enemy towards me instead of away. I would assume normally if I hit my opponent in the chest with a projectile that he would fly away from me.

I put the force magnitude at 3 and force frames at 10.
 
Last edited:

Andrew

Moderator
Staff member
Try adjusting the force amount in the magic item's "Add Force" impact action, found here:

1593599878677.png
 

zoicelols

Member
For some reason add force has no effect on the enemy. I even tried each different setting on it. The only one that seems to add any kind of force to my enemies is Damage with force magnitude option.
 

Andrew

Moderator
Staff member
The order of the Impact Actions matters. If you put Damage above Add Force, the force won't be applied. Adding the Add Force action like so to the demo Fireball should give you the result you need:

1593687390361.png

I'm not entirely sure what causes the force direction to be reversed in the first case, but using a negative Z value seems to be what you're after.
 

Andrew

Moderator
Staff member
Are you attempting to move a character object? If so, you'll need to apply the movement, animation etc. to that character component manually. You could do this with an ability on the target character which gets triggered when the magic projectile collides with it, such as by sub-classing MagicProjectile for the specific magic projectile you want this effect to happen with and add the following code to OnCollision:

C#:
    using Opsive.UltimateCharacterController.Character;
    using Opsive.UltimateCharacterController.Character.Abilities;
   
    ...

    protected override void OnCollision(RaycastHit? hit)
        {
            ...
           
            // NEW CODE STARTS
            if (hit.Value.transform.gameObject.layer == 26) { // Check if target is Enemy
                var characterLocomotion = hit.Value.transform.gameObject.GetComponent<UltimateCharacterLocomotion>();
                var jumpAbility = characterLocomotion.GetAbility<Jump>();
                characterLocomotion.TryStartAbility(jumpAbility);
            }
            // NEW CODE ENDS

            m_MagicItem.PerformImpact(m_CastID, m_GameObject, hit.Value.transform.gameObject, hit.Value);
           
            ...
        }
I tested this in the demo scene by adding the default Jump ability (with its Start Type set to Manual) to a new agent character in the magic room. Hitting it with a Fireball causes it to trigger the Jump ability. You would of course need to create your own ability that starts any movement, animation, etc. on the target character you want.
 

zoicelols

Member
I turned off magicprojectile on my projectile and added the new script HitByMagic to the projectile and now it makes him jump when hit.

Do I need to copy paste everything from the MagicProjectile script over to my HitByMagic script for it to work the same? Or does it inherit all of the custom everything in it just by subclassing?


Code:
namespace Opsive.UltimateCharacterController.Objects.ItemAssist
{
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using Opsive.UltimateCharacterController.Character;
    using Opsive.UltimateCharacterController.Character.Abilities;

    using Opsive.Shared.Game;
    using Opsive.UltimateCharacterController.Items.Actions;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
    using Opsive.UltimateCharacterController.Networking.Game;
#endif
    using Opsive.UltimateCharacterController.Objects;
    public class HitByMagic : MagicProjectile
    {

        private void ReturnToObjectPool()
        {
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
            if (NetworkObjectPool.IsNetworkActive()) {
                // The object may have already been destroyed over the network.
                if (!m_GameObject.activeSelf) {
                    return;
                }
                NetworkObjectPool.Destroy(m_GameObject);
                return;
            }
#endif
            ObjectPool.Destroy(m_GameObject);
        }
        protected override void OnCollision(RaycastHit? hit)
        {


            // NEW CODE STARTS
            if (hit.Value.transform.gameObject.layer == 26)
            { // Check if target is Enemy
                var characterLocomotion = hit.Value.transform.gameObject.GetComponent<UltimateCharacterLocomotion>();
                var jumpAbility = characterLocomotion.GetAbility<Jump>();
                characterLocomotion.TryStartAbility(jumpAbility);
            }
            // NEW CODE ENDS

            m_MagicItem.PerformImpact(m_CastID, m_GameObject, hit.Value.transform.gameObject, hit.Value);

            // Destroys the projectile when it has collided with an object.
            if (m_DestroyOnCollision)
            {
                // The projectile can wait for any particles to stop emitting.
                var immediateDestroy = !m_WaitForParticleStop;
                if (!immediateDestroy)
                {
                    var particleSystem = m_GameObject.GetCachedComponent<ParticleSystem>();
                    if (particleSystem != null)
                    {
                        particleSystem.Stop(true, ParticleSystemStopBehavior.StopEmitting);
                        Scheduler.Schedule(particleSystem.main.duration, ReturnToObjectPool);
                        immediateDestroy = false;
                    }
                }
                if (immediateDestroy)
                {
                    ReturnToObjectPool();
                }
                else
                {
                    // The projectile is waiting on the particles to be destroyed. Stop moving.
                    Stop();
                }
            }


        }
    }

}
 
Last edited:

Andrew

Moderator
Staff member
You can just subclass it and only override the parts you need to, in this case the OnCollision method.
 

zoicelols

Member
When I only subclassed the collision part there was undestroyed particles after cast on mine. So i also copied the objectpool destroy part and then it worked. Thats why i ask. For some reason it didnt inherit that part?
 

Andrew

Moderator
Staff member
Ah, I see. This is because that method is private, meaning that only the class that defines it has access to it. Protected methods, on the other hand, are accessible by derived classes.
 
Top