using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Sci-Fi Ship Controller. Copyright (c) 2018-2023 SCSM Pty Ltd. All rights reserved.
namespace SciFiShipController
{
///
/// Demo script that uses your pre-configured Docking Station for an AI Ship to undock,
/// fly along a path, then dock with another Docking Station.
/// This is designed to work with TechDemo4scene2 but a similar script could be adapted
/// to work with your scenario.
/// 1. Add this component to a gameobject in the scene
/// 2. Add two Docking Stations to your scene
/// 3. Configure a Ship Docking Point on each Ship Docking Station
/// 4. Drag each of the Ship Docking Stations from the scene into the slots provided on this component
/// 5. Add a NPC ship with ShipDocking and ShipAIInputModules attached
/// 6. On one of the Docking Stations, drag the NPC ship into the Ship Docking Station Point (Assign Ship)
/// 7. In the scene, ensure there is a SSCManager.
/// 8. Create a path between station 1 and station 2 (leave a gap between the start/end of the path and the stations)
/// 9. Click (I)nsert button on path to create a duplicate of the first path and rename it
/// 10. Reverse the direction of the new path using the reverse (<->) button
/// 11. Add the names of the paths to this component in the inspector
/// 12. On the ShipDocking component (on the NPC ship), set the Initial Docking State to Docked.
/// 13. On the ShipDocking component (on the NPC ship), optionally set the Auto Undock Time.
/// WARNING: This is a DEMO script and is subject to change without notice during
/// upgrades. This is just to show you how to do things in your own code and namespace.
///
[HelpURL("http://scsmmedia.com/ssc-documentation")]
public class DemoDockingTransit : MonoBehaviour
{
#region Public Variables
public bool initialiseOnStart = false;
public ShipDockingStation shipDockingStation1 = null;
public ShipDockingStation shipDockingStation2 = null;
public string departTransitPathName = "Depart Transit Path";
public string returnTransitPathName = "Return Transit Path";
public ShipAIInputModule.AIObstacleAvoidanceQuality obsAvoidWhenDocking = ShipAIInputModule.AIObstacleAvoidanceQuality.Off;
public ShipAIInputModule.AIObstacleAvoidanceQuality obsAvoidWhenNoDocking = ShipAIInputModule.AIObstacleAvoidanceQuality.Medium;
#endregion
#region Public Properties
public bool IsInitialised { get { return isInitialised; } }
#endregion
#region Public Static Variables
#endregion
#region Private Variables - General
private bool isInitialised = false;
private SSCManager sscManager = null;
private PathData departTransitPath = null;
private PathData returnTransitPath = null;
private List aiShips = null;
#endregion
#region Public Delegates
#endregion
#region Private Initialise Methods
void Start()
{
if (initialiseOnStart) { Initialise(); }
}
#endregion
#region Update Methods
#endregion
// Create additional regions for specific Private method groups
#region Private and Internal Methods - General
private void ConfigureAssignedShips (ShipDockingStation shipDockingStation)
{
int numDockingPoints = shipDockingStation.NumberOfDockingPoints;
for (int dpIdx = 0; dpIdx < numDockingPoints; dpIdx++)
{
ShipControlModule shipControlModule = shipDockingStation.GetAssignedShip(dpIdx);
if (shipControlModule != null)
{
// Tell the AI ship to take action when it has finished following a path
ShipAIInputModule shipAIInputModule = shipControlModule.GetShipAIInputModule(true);
if (shipAIInputModule != null && shipAIInputModule.IsInitialised)
{
shipAIInputModule.callbackCompletedStateAction = CompletedStateActionCallback;
// Remember this ship
aiShips.Add(shipAIInputModule);
}
// The ship should already know about it's docking point component, as it was discovered
// when the ship was assigned to the docking point in ShipDockingStation.Initialise().
ShipDocking shipDocking = shipControlModule.GetShipDocking(false);
// Get notified when a ship changes it's docking state (Docking, Docked, Undocking, Undocked)
if (shipDocking != null)
{
shipDocking.callbackOnStateChange = OnDockingStateChanged;
}
}
}
}
#endregion
#region Events
#endregion
#region Call back notifications
///
/// Take action when a ship finished it's current action
///
///
public void CompletedStateActionCallback (ShipAIInputModule shipAIInputModule)
{
if (shipAIInputModule != null)
{
// Ww are only interested in knowing when the ship is not docking, undocking or docked.
// i.e. Has just finished undocking OR has reached the end of the depart or return path.
ShipControlModule shipControlModule = shipAIInputModule.GetShipControlModule;
if (shipControlModule.ShipIsNotDocked())
{
PathData pathToFollow = shipAIInputModule.GetTargetPath();
// Was the ship following the depart path?
if (pathToFollow != null && pathToFollow.Equals(departTransitPath))
{
shipDockingStation2.AssignShipToDockingPoint(shipControlModule, shipControlModule.GetShipDocking(false));
shipDockingStation2.DockShip(shipControlModule);
}
// Was the ship following the return path?
else if (pathToFollow != null && pathToFollow.Equals(returnTransitPath))
{
shipDockingStation1.AssignShipToDockingPoint(shipControlModule, shipControlModule.GetShipDocking(false));
shipDockingStation1.DockShip(shipControlModule);
}
else
{
// Which station was it assigned to?
if (shipDockingStation1.IsShipAssigned(shipControlModule.GetShipId))
{
pathToFollow = departTransitPath;
shipDockingStation1.UnassignShip(shipControlModule.GetShipId);
}
else
{
// Assume assigned to second station
pathToFollow = returnTransitPath;
shipDockingStation2.UnassignShip(shipControlModule.GetShipId);
}
// Tell the ship to follow the appropriate path
shipAIInputModule.AssignTargetPath(pathToFollow);
shipAIInputModule.SetState(AIState.moveToStateID);
}
}
}
}
///
/// Gets called automatically when a ship's docking state changes.
/// (Docking, Docked, Undocking, Undocked)
///
///
///
///
///
public void OnDockingStateChanged (ShipDocking shipDocking, ShipControlModule shipControlModule, ShipAIInputModule shipAIInputModule, ShipDocking.DockingState previousDockingState)
{
int dockingStateInt = shipDocking.GetStateInt();
// Set the obstacle avoidance quality based on the docking state.
if (shipAIInputModule != null)
{
if (dockingStateInt == ShipDocking.notDockedInt)
{
shipAIInputModule.obstacleAvoidanceQuality = obsAvoidWhenNoDocking;
}
else
{
shipAIInputModule.obstacleAvoidanceQuality = obsAvoidWhenDocking;
}
}
}
#endregion
#region Public API Methods - General
///
/// If the ship is waiting (docked) at a station, attempt to get it
/// to travel to the other station.
///
///
public void DepartStation (ShipControlModule shipControlModule)
{
// Is ship docked?
if (isInitialised && shipControlModule != null && shipControlModule.ShipIsDocked())
{
// Now determine if it is docked with one of our stations
int dockingPointIdx = shipDockingStation1.GetDockingPointIndex(shipControlModule.GetShipId);
if (dockingPointIdx != ShipDockingStation.NoDockingPoint)
{
// Ship is assigned to Station 1.
DepartStation1(dockingPointIdx+1);
}
else
{
// Ship is not docked with Station 1, so check station 2.
dockingPointIdx = shipDockingStation2.GetDockingPointIndex(shipControlModule.GetShipId);
// Is ship assigned to Station 2?
if (dockingPointIdx != ShipDockingStation.NoDockingPoint)
{
// Ship is assigned to Station 2.
DepartStation2(dockingPointIdx+1);
}
}
}
}
///
/// Attempt to get the ship (if any) to undock and begin travelling to Station 2.
/// Assume the ship is an AI or AI-assisted ship.
///
///
public void DepartStation1 (int dockingPointNumber)
{
if (isInitialised)
{
shipDockingStation1.UnDockShip(dockingPointNumber - 1);
}
}
///
/// Attempt to get the ship (if any) to undock and begin travelling to Station 1.
/// Assume the ship is an AI or AI-assisted ship.
///
///
public void DepartStation2 (int dockingPointNumber)
{
if (isInitialised)
{
shipDockingStation2.UnDockShip(dockingPointNumber - 1);
}
}
///
/// Initialise this demo component.
///
public void Initialise()
{
if (isInitialised) { return; }
sscManager = SSCManager.GetOrCreateManager();
departTransitPath = sscManager.GetPath(departTransitPathName);
returnTransitPath = sscManager.GetPath(returnTransitPathName);
aiShips = new List(5);
if (shipDockingStation1 == null)
{
#if UNITY_EDITOR
Debug.LogWarning("DemoDockingTransit - could not find ShipDockingStation1 - did you add it as a reference from the scene in the slot provided?");
#endif
}
else if (shipDockingStation2 == null)
{
#if UNITY_EDITOR
Debug.LogWarning("DemoDockingTransit - could not find ShipDockingStation2 - did you add it as a reference from the scene in the slot provided?");
#endif
}
else if (!shipDockingStation1.IsInitialised)
{
#if UNITY_EDITOR
Debug.LogWarning("ERROR: DemoDockingTransit " + shipDockingStation1.name + " should have Initialise On Awake enabled for this demo");
#endif
}
else if (!shipDockingStation2.IsInitialised)
{
#if UNITY_EDITOR
Debug.LogWarning("ERROR: DemoDockingTransit " + shipDockingStation2.name + " should have Initialise On Awake enabled for this demo");
#endif
}
else if (departTransitPath == null)
{
#if UNITY_EDITOR
Debug.LogWarning("DemoDockingTransit - could not find departTransitPath (" + departTransitPathName + ")" );
#endif
}
else if (returnTransitPath == null)
{
#if UNITY_EDITOR
Debug.LogWarning("DemoDockingTransit - could not find returnTransitPath (" + returnTransitPathName + ")" );
#endif
}
else
{
ConfigureAssignedShips(shipDockingStation1);
ConfigureAssignedShips(shipDockingStation2);
isInitialised = true;
}
}
#endregion
}
}