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 UnityEngine;
|
||||
using NanoBrain;
|
||||
|
||||
namespace Passer.CreatureControl {
|
||||
|
||||
/// <summary>
|
||||
/// Simulated ant using a NanoBrain
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Brain))]
|
||||
public class Ant : Insect {
|
||||
/// <summary>
|
||||
/// inertia controls how quickly the ant can change it direction
|
||||
/// </summary>
|
||||
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;
|
||||
/// <summary>
|
||||
/// The angle to the left and right within the ant can smell things
|
||||
/// </summary>
|
||||
private readonly float smellAngle = 80.0f;
|
||||
|
||||
public GameObject homePheromonePrefab;
|
||||
@ -18,16 +33,25 @@ namespace Passer.CreatureControl {
|
||||
|
||||
public Brain nanoBrain;
|
||||
// brain output
|
||||
public Neuron targetDirection;
|
||||
public Neuron hasFood;
|
||||
|
||||
// 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 hitLeft;
|
||||
public Nucleus hitRight;
|
||||
public Nucleus beat;
|
||||
public Receptor foodReceptor;
|
||||
public Receptor homeReceptor;
|
||||
|
||||
public Vector3 linearVelocity;
|
||||
public Vector3 linearVelocity = Vector3.forward;
|
||||
public Vector3 angularVelocity;
|
||||
|
||||
#region Init
|
||||
@ -49,30 +73,37 @@ namespace Passer.CreatureControl {
|
||||
|
||||
Cluster brain = this.nanoBrain.brain;
|
||||
if (brain != null) {
|
||||
// brain outputs
|
||||
this.pheromoneSteering = brain.GetNucleus("Pheromone Steering");
|
||||
//--- brain inputs
|
||||
|
||||
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.hitLeft = brain.GetNucleus("Hit Left");
|
||||
this.hitRight = brain.GetNucleus("Hit Right");
|
||||
this.foodReceptor = brain.GetNucleus("Food 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)
|
||||
touchLeft.touched += OnAntennaTouchLeft;
|
||||
if (touchRight != null)
|
||||
touchRight.touched += OnAntennaTouchRight;
|
||||
|
||||
StartCoroutine(Beat());
|
||||
}
|
||||
|
||||
#endregion Start
|
||||
@ -88,86 +119,56 @@ namespace Passer.CreatureControl {
|
||||
pheromoneObj.transform.position = this.model.position;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
public override void Update() {
|
||||
base.Update();
|
||||
|
||||
UpdateBeat();
|
||||
UpdateSmell();
|
||||
|
||||
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);
|
||||
UpdateMovement();
|
||||
}
|
||||
|
||||
public virtual void FixedUpdate() {
|
||||
CheckGrounded();
|
||||
}
|
||||
|
||||
public float beatInterval = 3;
|
||||
float lastBeatTime = 0;
|
||||
void UpdateBeat() {
|
||||
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);
|
||||
protected void UpdateMovement() {
|
||||
if (this.targetDirection == null || this.animator == null)
|
||||
return;
|
||||
|
||||
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);
|
||||
Vector3 randomDirection = Quaternion.AngleAxis(randomAngle, Vector3.up) * Vector3.forward * 1.01f;
|
||||
pheromoneSteering?.SetBias(randomDirection); //, 0, "random");
|
||||
Vector3 randomDirection = Quaternion.AngleAxis(randomAngle, Vector3.up) * Vector3.forward;
|
||||
pheromoneSteering?.SetBias(randomDirection);
|
||||
yield return _waitForSeconds3;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
foreach (Collider collider in colliders) {
|
||||
SmellPheromones(collider);
|
||||
@ -199,7 +200,6 @@ namespace Passer.CreatureControl {
|
||||
}
|
||||
//Debug.DrawLine(this.transform.position, pheromone.transform.position, Color.magenta);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SmellFood(Collider thing) {
|
||||
|
||||
@ -6,7 +6,10 @@ namespace Passer.CreatureControl {
|
||||
public float strength = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ BlendTree:
|
||||
m_Motion: {fileID: 7400000, guid: ab82ff68e62ea3b1c8e6523f8d46c142, type: 2}
|
||||
m_Threshold: 0.19200002
|
||||
m_Position: {x: -1, y: 0}
|
||||
m_TimeScale: 2
|
||||
m_TimeScale: 5
|
||||
m_CycleOffset: 0
|
||||
m_DirectBlendParameter: Forward
|
||||
m_Mirror: 0
|
||||
@ -36,7 +36,7 @@ BlendTree:
|
||||
m_Motion: {fileID: 7400000, guid: 91229db5e929c379bbfd5bf417848488, type: 2}
|
||||
m_Threshold: 0.28800002
|
||||
m_Position: {x: 1, y: 0}
|
||||
m_TimeScale: 2
|
||||
m_TimeScale: 1
|
||||
m_CycleOffset: 0
|
||||
m_DirectBlendParameter: Forward
|
||||
m_Mirror: 0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user