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:
This is what my settings look like:
And I have my Swim Ability started when the game starts.
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:
And I have my Swim Ability started when the game starts.