Initial Doxygen documentation
This commit is contained in:
parent
7ced91909a
commit
f2884327cf
8
Documentation.meta
Normal file
8
Documentation.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c2c74f5b3b38f630c9211ae171b6c481
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
14
Documentation/Ant2.md
Normal file
14
Documentation/Ant2.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
Lorum ipsum
|
||||||
|
|
||||||
|
Heading level 1
|
||||||
|
===============
|
||||||
|
|
||||||
|
Lorum ipsum
|
||||||
|
|
||||||
|
Heading Level 2
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Lorum ipsum
|
||||||
|
|
||||||
|
here is a an image:
|
||||||
|

|
||||||
7
Documentation/Ant2.md.meta
Normal file
7
Documentation/Ant2.md.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e216f4e0f4902417980c167612b0e0c1
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
2
Documentation/GettingStarted.md
Normal file
2
Documentation/GettingStarted.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/// \page GettingStarted Getttting Started
|
||||||
|
Getting starttted
|
||||||
7
Documentation/GettingStarted.md.meta
Normal file
7
Documentation/GettingStarted.md.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 02f2904aebc8f9475b2ab67bc25205f8
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
9
Documentation/Installation.md
Normal file
9
Documentation/Installation.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/// \page Installation Installation
|
||||||
|
|
||||||
|
You can import the NanoBrain Ant package in Unity directly with the Package Manager git package importer.
|
||||||
|
|
||||||
|
See Unity: [Installing from a Git URL](https://docs.unity3d.com/Manual/upm-ui-giturl.html)
|
||||||
|
|
||||||
|
Use the link from 'Clone with HTTP' (for example: https://git.passer.life/CreatureControl/Ant.git) In this way you can always retrieve the latest version by pressing the Update button in the Package Manager.
|
||||||
|
|
||||||
|
Optionally, you can use a tag to retrieve a specific version. For example: https://git.passer.life/CreatureControl/Ant.git#0.1.0. This will give you a stable version which does not change. Updating can be done by retrieving the package with a link to a new release.
|
||||||
7
Documentation/Installation.md.meta
Normal file
7
Documentation/Installation.md.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c97243ffb6244df0d9470dd96c86f8fc
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,2 +1,6 @@
|
|||||||
# Ant
|
# %NanoBrain Ant
|
||||||
|
|
||||||
|
Table of Contents
|
||||||
|
-----------------
|
||||||
|
- [Installation](\ref Installation)
|
||||||
|
- [Getting started](\ref GettingStarted)
|
||||||
@ -1,13 +1,28 @@
|
|||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using NanoBrain;
|
using NanoBrain;
|
||||||
|
|
||||||
namespace Passer.CreatureControl {
|
namespace Passer.CreatureControl {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simulated ant using a NanoBrain
|
||||||
|
/// </summary>
|
||||||
[RequireComponent(typeof(Brain))]
|
[RequireComponent(typeof(Brain))]
|
||||||
public class Ant : Insect {
|
public class Ant : Insect {
|
||||||
|
/// <summary>
|
||||||
|
/// inertia controls how quickly the ant can change it direction
|
||||||
|
/// </summary>
|
||||||
private readonly float inertia = 0.2f;
|
private readonly float inertia = 0.2f;
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum distance at which the ant can smell things
|
||||||
|
/// </summary>
|
||||||
|
/// The strength of the smell decreases with the inverse square law
|
||||||
|
/// to zero at this distance
|
||||||
private readonly float smellRadius = 0.2f;
|
private readonly float smellRadius = 0.2f;
|
||||||
|
/// <summary>
|
||||||
|
/// The angle to the left and right within the ant can smell things
|
||||||
|
/// </summary>
|
||||||
private readonly float smellAngle = 80.0f;
|
private readonly float smellAngle = 80.0f;
|
||||||
|
|
||||||
public GameObject homePheromonePrefab;
|
public GameObject homePheromonePrefab;
|
||||||
@ -18,16 +33,25 @@ namespace Passer.CreatureControl {
|
|||||||
|
|
||||||
public Brain nanoBrain;
|
public Brain nanoBrain;
|
||||||
// brain output
|
// brain output
|
||||||
|
public Neuron targetDirection;
|
||||||
public Neuron hasFood;
|
public Neuron hasFood;
|
||||||
|
|
||||||
// brain input
|
// brain input
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The (heart) beat for the brain
|
||||||
|
/// </summary>
|
||||||
|
/// It is used by the brain to do things periodically
|
||||||
|
/// like placing pheromones
|
||||||
|
public Nucleus beat;
|
||||||
|
|
||||||
public Nucleus pheromoneSteering;
|
public Nucleus pheromoneSteering;
|
||||||
public Nucleus hitLeft;
|
public Nucleus hitLeft;
|
||||||
public Nucleus hitRight;
|
public Nucleus hitRight;
|
||||||
public Nucleus beat;
|
|
||||||
public Receptor foodReceptor;
|
public Receptor foodReceptor;
|
||||||
public Receptor homeReceptor;
|
public Receptor homeReceptor;
|
||||||
|
|
||||||
public Vector3 linearVelocity;
|
public Vector3 linearVelocity = Vector3.forward;
|
||||||
public Vector3 angularVelocity;
|
public Vector3 angularVelocity;
|
||||||
|
|
||||||
#region Init
|
#region Init
|
||||||
@ -49,30 +73,37 @@ namespace Passer.CreatureControl {
|
|||||||
|
|
||||||
Cluster brain = this.nanoBrain.brain;
|
Cluster brain = this.nanoBrain.brain;
|
||||||
if (brain != null) {
|
if (brain != null) {
|
||||||
// brain outputs
|
//--- brain inputs
|
||||||
this.pheromoneSteering = brain.GetNucleus("Pheromone Steering");
|
|
||||||
|
|
||||||
if (brain.GetNucleus("Home Pheromones") is Neuron homePheromones)
|
|
||||||
homePheromones.WhenFiring += PlaceHomePheromone;
|
|
||||||
if (brain.GetNucleus("Food Pheromones") is Neuron foodPheromones)
|
|
||||||
foodPheromones.WhenFiring += PlaceFoodPheromone;
|
|
||||||
|
|
||||||
this.hasFood = brain.GetNucleus("Having Food") as Neuron;
|
|
||||||
// brain inputs
|
|
||||||
this.beat = brain.GetNucleus("Beat");
|
this.beat = brain.GetNucleus("Beat");
|
||||||
this.hitLeft = brain.GetNucleus("Hit Left");
|
this.hitLeft = brain.GetNucleus("Hit Left");
|
||||||
this.hitRight = brain.GetNucleus("Hit Right");
|
this.hitRight = brain.GetNucleus("Hit Right");
|
||||||
this.foodReceptor = brain.GetNucleus("Food Receptor") as Receptor;
|
this.foodReceptor = brain.GetNucleus("Food Receptor") as Receptor;
|
||||||
this.homeReceptor = brain.GetNucleus("Home Receptor") as Receptor;
|
this.homeReceptor = brain.GetNucleus("Home Receptor") as Receptor;
|
||||||
|
this.pheromoneSteering = brain.GetNucleus("Pheromone Steering");
|
||||||
|
|
||||||
|
//--- brain outputs
|
||||||
|
this.targetDirection = brain.defaultOutput;
|
||||||
|
|
||||||
|
// Try to find the Home Pheromones Neuron
|
||||||
|
if (brain.GetNucleus("Home Pheromones") is Neuron homePheromones)
|
||||||
|
// and call PlaceHomePheromone when it is firing
|
||||||
|
homePheromones.WhenFiring += PlaceHomePheromone;
|
||||||
|
// Try to find the Food Pheromones Neuron
|
||||||
|
if (brain.GetNucleus("Food Pheromones") is Neuron foodPheromones)
|
||||||
|
// and call PlaceFoodPheromone when it is firing
|
||||||
|
foodPheromones.WhenFiring += PlaceFoodPheromone;
|
||||||
|
|
||||||
|
this.hasFood = brain.GetNucleus("Having Food") as Neuron;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.linearVelocity = Vector3.forward;
|
// Initialize the callbacks for the antenna colliders
|
||||||
|
|
||||||
if (touchLeft != null)
|
if (touchLeft != null)
|
||||||
touchLeft.touched += OnAntennaTouchLeft;
|
touchLeft.touched += OnAntennaTouchLeft;
|
||||||
if (touchRight != null)
|
if (touchRight != null)
|
||||||
touchRight.touched += OnAntennaTouchRight;
|
touchRight.touched += OnAntennaTouchRight;
|
||||||
|
|
||||||
|
StartCoroutine(Beat());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Start
|
#endregion Start
|
||||||
@ -88,86 +119,56 @@ namespace Passer.CreatureControl {
|
|||||||
pheromoneObj.transform.position = this.model.position;
|
pheromoneObj.transform.position = this.model.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update is called once per frame
|
|
||||||
public override void Update() {
|
public override void Update() {
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
UpdateBeat();
|
|
||||||
UpdateSmell();
|
UpdateSmell();
|
||||||
|
UpdateMovement();
|
||||||
if (this.nanoBrain == null || this.nanoBrain.brain == null || this.animator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Vector3 localForce = nanoBrain.brain.defaultOutput.outputValue;
|
|
||||||
//Vector3 localForce = this.transform.InverseTransformDirection(worldForce);
|
|
||||||
|
|
||||||
this.linearVelocity = (1 - inertia) * (Time.deltaTime * localForce.normalized) + inertia * this.linearVelocity;
|
|
||||||
this.linearVelocity = this.linearVelocity.normalized; // * this.forwardSpeed;
|
|
||||||
|
|
||||||
//this.animator.SetFloat("Forward", this.forwardSpeed); //this.linearVelocity.z * this.forwardSpeed);
|
|
||||||
float forwardParam = Mathf.Clamp01(this.linearVelocity.z); // / this.forwardSpeed);
|
|
||||||
float angleDeg = 0;
|
|
||||||
if (this.linearVelocity.magnitude > 1e-5f)
|
|
||||||
angleDeg = Mathf.Atan2(this.linearVelocity.x, this.linearVelocity.z) * Mathf.Rad2Deg;
|
|
||||||
|
|
||||||
// base turn in -1..1
|
|
||||||
float baseTurn = Mathf.Clamp(angleDeg / 45, -1f, 1f);
|
|
||||||
float turnParam = baseTurn; // * Mathf.Max(0.6f, 1 - forwardParam);
|
|
||||||
|
|
||||||
// Rotate towards the movement direction
|
|
||||||
// if (this.linearVelocity != Vector3.zero) {
|
|
||||||
// Quaternion targetRotation = Quaternion.LookRotation(this.linearVelocity);
|
|
||||||
// Quaternion worldRotation = transform.rotation * targetRotation;
|
|
||||||
// Quaternion deltaRotation = worldRotation * Quaternion.Inverse(transform.rotation);
|
|
||||||
|
|
||||||
// Vector3 eulerAngleChange = deltaRotation.eulerAngles;
|
|
||||||
// // Normalize the Euler angles to avoid unexpected jumps due to 360-degree rotations
|
|
||||||
// eulerAngleChange = new Vector3(
|
|
||||||
// LinearAlgebra.Angles.Normalize(eulerAngleChange.x),
|
|
||||||
// LinearAlgebra.Angles.Normalize(eulerAngleChange.y),
|
|
||||||
// LinearAlgebra.Angles.Normalize(eulerAngleChange.z)
|
|
||||||
// );
|
|
||||||
|
|
||||||
// float rotSpeed = (eulerAngleChange.y / 45) * this.rotationSpeed;
|
|
||||||
// this.animator.SetFloat("Rotate", rotSpeed);
|
|
||||||
// Debug.Log($"fw {this.forwardSpeed} ang {rotSpeed}");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Smooth against current animator values
|
|
||||||
// float curF = animator.GetFloat("Forward");
|
|
||||||
// float curT = animator.GetFloat("Turn");
|
|
||||||
// forwardParam = Mathf.Lerp(curF, forwardParam, 1f - Mathf.Exp(-10 * Time.deltaTime));
|
|
||||||
// turnParam = Mathf.Lerp(curT, turnParam, 1f - Mathf.Exp(-10 * Time.deltaTime));
|
|
||||||
|
|
||||||
|
|
||||||
this.animator.SetFloat("Forward", forwardParam);
|
|
||||||
this.animator.SetFloat("Rotate", turnParam);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void FixedUpdate() {
|
public virtual void FixedUpdate() {
|
||||||
CheckGrounded();
|
CheckGrounded();
|
||||||
}
|
}
|
||||||
|
|
||||||
public float beatInterval = 3;
|
protected void UpdateMovement() {
|
||||||
float lastBeatTime = 0;
|
if (this.targetDirection == null || this.animator == null)
|
||||||
void UpdateBeat() {
|
return;
|
||||||
if (lastBeatTime == 0) {
|
|
||||||
ulong delay = (ulong)(Random.value * beatInterval);
|
|
||||||
lastBeatTime = Time.time - delay;
|
|
||||||
}
|
|
||||||
if (Time.time - lastBeatTime >= beatInterval) {
|
|
||||||
lastBeatTime = Time.time;
|
|
||||||
beat?.SetBias(Vector3.one); //, 0);
|
|
||||||
|
|
||||||
|
Vector3 movementDir = this.targetDirection.outputValue;
|
||||||
|
this.linearVelocity =
|
||||||
|
(1 - this.inertia) * (Time.deltaTime * movementDir.normalized) +
|
||||||
|
this.inertia * this.linearVelocity;
|
||||||
|
this.linearVelocity = this.linearVelocity.normalized;
|
||||||
|
|
||||||
|
float forwardParam = this.linearVelocity.z;
|
||||||
|
|
||||||
|
float angleRad = this.linearVelocity.sqrMagnitude > 1e-10f ?
|
||||||
|
Mathf.Atan2(this.linearVelocity.x, this.linearVelocity.z) :
|
||||||
|
0;
|
||||||
|
// map -20..20 degrees to -1..1
|
||||||
|
float rotateParam = Mathf.Clamp(angleRad * 3, -1f, 1f);
|
||||||
|
|
||||||
|
this.animator.SetFloat("Forward", forwardParam);
|
||||||
|
this.animator.SetFloat("Rotate", rotateParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly WaitForSeconds _waitForSeconds3 = new(3);
|
||||||
|
IEnumerator Beat() {
|
||||||
|
while (Application.isPlaying) {
|
||||||
|
// Beat signal to the brain
|
||||||
|
beat?.SetBias(Vector3.one);
|
||||||
|
|
||||||
|
// Set random direction to simulate noisy smells perception
|
||||||
|
// which will result in a bit of random walking when no clear
|
||||||
|
// smells are received
|
||||||
float randomAngle = Random.Range(-smellAngle, smellAngle);
|
float randomAngle = Random.Range(-smellAngle, smellAngle);
|
||||||
Vector3 randomDirection = Quaternion.AngleAxis(randomAngle, Vector3.up) * Vector3.forward * 1.01f;
|
Vector3 randomDirection = Quaternion.AngleAxis(randomAngle, Vector3.up) * Vector3.forward;
|
||||||
pheromoneSteering?.SetBias(randomDirection); //, 0, "random");
|
pheromoneSteering?.SetBias(randomDirection);
|
||||||
|
yield return _waitForSeconds3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateSmell() {
|
void UpdateSmell() {
|
||||||
// To generate random basic movement, we add a small with a random direction with low intensity
|
|
||||||
|
|
||||||
Collider[] colliders = Physics.OverlapSphere(this.transform.position, smellRadius);
|
Collider[] colliders = Physics.OverlapSphere(this.transform.position, smellRadius);
|
||||||
foreach (Collider collider in colliders) {
|
foreach (Collider collider in colliders) {
|
||||||
SmellPheromones(collider);
|
SmellPheromones(collider);
|
||||||
@ -199,7 +200,6 @@ namespace Passer.CreatureControl {
|
|||||||
}
|
}
|
||||||
//Debug.DrawLine(this.transform.position, pheromone.transform.position, Color.magenta);
|
//Debug.DrawLine(this.transform.position, pheromone.transform.position, Color.magenta);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SmellFood(Collider thing) {
|
void SmellFood(Collider thing) {
|
||||||
|
|||||||
@ -6,7 +6,10 @@ namespace Passer.CreatureControl {
|
|||||||
public float strength = 1;
|
public float strength = 1;
|
||||||
|
|
||||||
public float StrengthAt(float distance) {
|
public float StrengthAt(float distance) {
|
||||||
float intensity = this.strength * (1 / distance);
|
if (distance <= 0)
|
||||||
|
return this.strength;
|
||||||
|
|
||||||
|
float intensity = this.strength / (4.0f * Mathf.PI * distance * distance);
|
||||||
return intensity;
|
return intensity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ BlendTree:
|
|||||||
m_Motion: {fileID: 7400000, guid: ab82ff68e62ea3b1c8e6523f8d46c142, type: 2}
|
m_Motion: {fileID: 7400000, guid: ab82ff68e62ea3b1c8e6523f8d46c142, type: 2}
|
||||||
m_Threshold: 0.19200002
|
m_Threshold: 0.19200002
|
||||||
m_Position: {x: -1, y: 0}
|
m_Position: {x: -1, y: 0}
|
||||||
m_TimeScale: 2
|
m_TimeScale: 5
|
||||||
m_CycleOffset: 0
|
m_CycleOffset: 0
|
||||||
m_DirectBlendParameter: Forward
|
m_DirectBlendParameter: Forward
|
||||||
m_Mirror: 0
|
m_Mirror: 0
|
||||||
@ -36,7 +36,7 @@ BlendTree:
|
|||||||
m_Motion: {fileID: 7400000, guid: 91229db5e929c379bbfd5bf417848488, type: 2}
|
m_Motion: {fileID: 7400000, guid: 91229db5e929c379bbfd5bf417848488, type: 2}
|
||||||
m_Threshold: 0.28800002
|
m_Threshold: 0.28800002
|
||||||
m_Position: {x: 1, y: 0}
|
m_Position: {x: 1, y: 0}
|
||||||
m_TimeScale: 2
|
m_TimeScale: 1
|
||||||
m_CycleOffset: 0
|
m_CycleOffset: 0
|
||||||
m_DirectBlendParameter: Forward
|
m_DirectBlendParameter: Forward
|
||||||
m_Mirror: 0
|
m_Mirror: 0
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user