Swim Height Detection Ability

nathanj

Member
OK, I think I finally have this working. It is a Swim height detection script for enabling swimming with assets like R.A.M. and others where the water height isnot a simple value but changes dynamically. It adds a custom raycast above the player and points down to detect when the water (set to the layer "Water") is within range and applies the y position value to the swim height detection (water Height detection Method is set to Custom) on the Swim ability).

Should also mention that I ended up using @Janooba 's custom raycast as a template for this. https://www.opsive.com/forum/index.php?threads/interact-using-screen-raycast.913/

Add this script to the Swimming Addon's Scripts folder:

Code:
namespace Opsive.UltimateCharacterController.Character.Abilities
{
    using Opsive.Shared.Events;
    using Opsive.Shared.Game;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
using Opsive.UltimateCharacterController.Networking;
#endif
    using Opsive.UltimateCharacterController.Traits;
    using Opsive.UltimateCharacterController.Objects.CharacterAssist;
    using Opsive.UltimateCharacterController.Utility;
    using UnityEngine;
    using Opsive.UltimateCharacterController.AddOns.Swimming;

    /// <summary>
    /// Interacts with another object within the scene. The object that the ability interacts with must have the Interact component added to it.
    /// </summary>
    [DefaultStartType(AbilityStartType.Automatic)]
    [DefaultObjectDetection(ObjectDetectionMode.Customcast)]
    [DefaultUseLookDirection(false)]
    [DefaultCastOffset(0,2,0)]
    [DefaultAbilityIndex(-1)]
    [DefaultAllowPositionalInput(false)]
    [DefaultAllowRotationalInput(false)]

    public class SwimHeightDetection : DetectObjectAbilityBase
    {
        private Swim m_SwimAbility;
        private bool setWaterTo0 = false;
        /// <summary>
        /// Initialize the default values.
        /// </summary>
        public override void Awake()
        {
            base.Awake();
            m_SwimAbility = m_CharacterLocomotion.GetAbility<Swim>();
        }
     
        /// <summary>
        /// Called when the ablity is tried to be started. If false is returned then the ability will not be started.
        /// </summary>
        /// <returns>True if the ability can be started.</returns>
        public override bool CanStartAbility()
        {
            if(!DetectUsingRaycast())
            {
                if (setWaterTo0)
                {
                    if (m_DetectedObject == null && !m_SwimAbility.IsActive)
                    {
                        //Debug.Log("swimmimg height detecion stopped");
                        m_SwimAbility.SetWaterSurfacePosition(0f);
                        setWaterTo0 = false;
                    }
                    m_DetectedObject = null;
                    return false;
               }
            }
            return false;
        }
        private bool DetectUsingRaycast()
        {
            if (Physics.Raycast(m_Transform.TransformPoint(m_CastOffset), -m_Transform.up, out m_RaycastResult, m_CastDistance, m_DetectLayers, m_TriggerInteraction))
            {
                var hitObject = m_RaycastResult.collider.gameObject;
                if (ValidateObject(hitObject, m_RaycastResult))
                {
                        m_DetectedObject = hitObject;
                        m_SwimAbility.SetWaterSurfacePosition(m_RaycastResult.point.y);
                        //Debug.Log(m_RaycastResult.point.y + "  water height");
                        if (!setWaterTo0) setWaterTo0 = true;
                        return true;
                 
                }
            }
            if (m_DetectedObject) m_DetectedObject = null;
            return false;
        }

        public override void OnDestroy()
        {
            base.OnDestroy();

        }
    }
}

This is what my settings look like:
customRaycastSwim.PNG

And I have my Swim Ability started when the game starts.
 

nathanj

Member
I can do this tomorrow. Do you have the swim pack installed and the swim ability set up? Is it set to start on awake somehow? ATM i'm using this crappy system where i have a box collider the size of the whole scene to enable the swim ability. For soem reason when I set it to start with Manual and try calling .TryAbilityStart(Swim) my player won't move.

Also, do you have a Mesh Collider on your water source with the layer set to "Water"?
 

MoveRotateResize

New member
Ya I have both packs installed and they are working perfectly. Swimming in RAM 2019 lakes works but not rivers. I have a box collider on my river and the 301 object identifier script on my river too. I added the swim section script and the ability but it still doesn't work. My character swims whenever he hits the box collider for the river (which is huge haha)
 

nathanj

Member
Ok, so that big box collider, change it to something other than water and make sure it matches your swim detection layer. The water layer should only be detected by the raycasts.

I’m away from my computer for the day, so sorry I can’t send any images. If your still stuck tomorrow I will then.
 

MoveRotateResize

New member
Box Collider.jpg


Swim Ability.jpgSwim Height Detection Ability.jpg
Here's some pics of my settings. I have the box colider setup, a swim height detection ability, and the swimming ability set up so far. With these current settings my Character instantly starts swimming when I press the play button
 
Top