====== Scripting API ====== Brief description of the most important classes and functions. \\ Almost every parameter in every component can be changed runtime from code. \\ For exact behaviour and more - check source code. ===== DragonWaterManager ===== This is main singleton class that controls everything about the water. public class DragonWaterManager { // static getter to get singleton instance public static DragonWaterManager Instance { get; } // acces to configuration scriptable object public DragonWaterConfig Config { get; } public float Time { get; set; } // current simulation time - if you disable auto simulation, you''ll have to update this value manually every frame public WaterSurface UnderwaterSurface { get; } // surface that main camera is currently below; null if none public WaterSampler.HitResult CameraHitResult { get; } // last camera hit test against water, used for auto snapping and underwater detection public Camera MainCamera { get; } // refers to Camera.Main // subscribe to this event to receive callback when camera changes underwater state // both, from and to param can be null depending on if you dive, resurface, or change between surface under water public delegate void UnderwaterChangedCallback(WaterSurface from, WaterSurface to); public event UnderwaterChangedCallback OnUnderwaterChanged; // collections public IReadOnlyList Surfaces { get; } // currently active surfaces public WaterSurface DefaultSurface { get; } // current default and active surface, null if not set public IReadOnlyList { get; } // currently active ripple projectors public IReadOnlyList { get; } // currently active local wave areas // culling - used internally by WaterSampler public void CullWaterSurfaces(ref Bounds bounds, ref List list); public void CullCutoutColliders(ref Bounds bounds, ref List list); // sampling water public WaterSampler.HitResult SampleWater(Vector3 position); // calls SampleWater with considerCutouts=true as default public WaterSampler.HitResult SampleWater(Vector3 position, bool considerCutouts); } ---- ===== WaterSampler ===== The most usefull class. \\ Create it's object to sample water. \\ You can reuse this object (keep calling Schedule and Complete) but **always remember to Dispose() when no longer needed.** public class WaterSampler : IDisposable { public static IReadOnlyList ActiveSamplers { get; } // access to all currently active samplers public enum SurfaceDetectionMode { Default, // use default surface, if its null then fallbacks to AutoCull AutoCull, // automatically scans nearby surfaces Custom // tests only aainst provided surfaces in SurfaceDetectionCustom list } public enum CutoutDetectionMode { AutoCull, // automatically scans nearby colliders to cutout DontCutout, // do not care about cutouts at all - always sample Custom // tests only against provided cutouts in CutoutDetectionCustom list } public int Precision = 0; // amount of iterations; 0 refers to Constants.DefaultSamplerPrecision and 3-4 is most cases is more than enough public SurfaceDetectionMode SurfaceDetection = SurfaceDetectionMode.Default; // how nearby surfaces are detected public CutoutDetectionMode CutoutDetection = CutoutDetectionMode.AutoCull; // how to to process cutout volumes public List SurfaceDetectionCustom = null; // you NEED to assign it in case of Custom mode public List CutoutDetectionCustom = null; // you NEED to assign it in case of Custom mode public Bounds CullingBox = default; // if left default, it will automatically create bounding box for all points before scheduling public int MaxSize { get; }; // maximum amount of points this sampler can process; assigned via constructor public bool IsRunning { get; }; // if its running, you shouldn't modify anything here public HitResult[] Results { get; } // access to array of results of last scan - it's size is always MaxSize even if you ran it for less points public int ResultCount { get; } // actual amount of available results in Results array public WaterSampler(int maxSize = 1); // construction - you have to specify max size public void Dispose(); // ALWAYS remember to dispose no longer needed sampler public void Resize(int newMaxSize); // resize to new MaxSize // fill points to test against water public void SetPoint(int index, Vector3 point); // set single point and specified index public void SetPoints(IReadOnlyList points); // set points since index 0 public void SetPoints(ArraySegment points); // set points since index 0 // schedule public void Schedule(); // calls Schedule with MaxSize public void Schedule(int pointsCount); // amount of points to process starting from index 0; can't be larger than MaxSize public void Complete(); // complete processing - recommended to call next frame // caching auto culls // be default AutoCull modes are very expensive - with this functions you can temporarily cache their result so it will act like Custom options public void CacheAutoCull(); // calls CacheAutoCull with MaxSize public void CacheAutoCull(int points); public void ClearAutoCullCache(); // clears sampler until next scheduling, so it acts like not scheduled yet at all with no results public void ClearState(); } ---- ==== WaterSampler.HitResult ==== Struct that contains sampling result of a single point against water. public struct HitResult { public Vector3 sampledPoint; public WaterSurface surface; // null if no surface detected public Vector3 hitPoint; // actual position on water surface, possibly very closely to sampledPoint public Vector3 hitNormal; // normal vector of water here public bool HasHit => surface != null; public bool IsUnderwater => sampledPoint.y < hitPoint.y; public float Depth => hitPoint.y - sampledPoint.y; // positive when under water public float Height => sampledPoint.y - hitPoint.y; // positive when above water public float WaterLevel => hitPoint.y; } ---- ===== WaterBehaviour ===== Abstract MonoBehaviour class than can be used as utility for easier water sampling from your game object component. \\ You can treat is as a MonoBehaviour facade to WaterSampler. \\ It uses WaterSampler asyncrhonously, so it always generates one frame delay while sampling water, which is totally fine in most cases. public abstract class WaterBehaviour : MonoBehaviour { // used to configure component from inspector [Serializable] public class WaterSamplerConfig { /* .. */ } // access to config that is exposed for configuration via inspector public WaterSamplerConfig SamplerConfig {get; }; public int FrameDividerOffset { get; }; // check this inside InnerFixedUpdate if you want to schedule protected bool isSchedulingFrane { get; }; // direct access to array with points you are going to sample protected Vector3[] samplingPoints { get; }; // Unity callbacks protected virtual void Awake(); protected virtual void OnEnable(); protected virtual void OnDisable(); protected virtual void OnDestroy(); protected virtual void OnFixedUpdate(); // in most cases, do not override this function (see InnerFixedUpdate) // prepare sampler side before settingg any points protected void PrepareSamplingPointsSize(int size); protected void SetSamplingPoint(int index, Vector3 point); protected void SetSamplingPoints(Vector3[] points); protected int GetResultCount(); // return amount of available results protected WaterSampler.HitResult GetResult(int index); protected void GetResults(out ArraySegment results); // override this function for actual fixed update behaviour // only inside this function you can schedule points protected virtual void InnerFixedUpdate() { } } ---- ==== FloatingBody ==== FloatingBody is built-in implementation of WaterBehaviour. public class FloatingBody : WaterBehaviour { // getters and setters for all properties you see in the inspector public Vector3 CenterOfMass { get; set; } public float BuoyancyForce { get; set; } public bool IgnoreMass { get; set; } public float NormalAlignment { get; set; } public float Instability { get; set; } public float SubmergeDrag { get; set; } public float SubmergeAngularDrag { get; set; } public float CurrentSubmergeLevel { get; } // range 0-1 thats means fraction of points that are under water public Rigidbody Rigidbody { get; } // return attached rigidbody // modify contact points (all in local space of game object) public Vector3 GetContactPoint(int index); public void SetContactPoint(int index, Vector3 point); public void RemoveContactPoint(int index); public void AddContactPoint(Vector3 point); // return last hit result for point with given index // useful e.g. to check if given part of body is above or under water without creating additional sampler or object for that public WaterSampler.HitResult GetContactPointHit(int index); }