Skip to content

Instantly share code, notes, and snippets.

@eelstork
Created October 11, 2020 10:29
Show Gist options
  • Save eelstork/da071e7d70faa3b3d570998e408c3617 to your computer and use it in GitHub Desktop.
Save eelstork/da071e7d70faa3b3d570998e408c3617 to your computer and use it in GitHub Desktop.
using Ex = System.Exception;
using T = UnityEngine.Transform; using UnityEngine;
using Active.Core; using static Active.Core.status; using Active.Util;
namespace Activ.Kabuki{
public class Actor : XTask{
public float speed = 1, rotationSpeed = 180;
public Transform hold; // for holding an object in hand
public Vector3 holdOffset;
public Transform[] pushingBones; // contact points for pushing
public Actor other; // for give/take interaction
public Transform gift;
// --------------------------------------------------------------
public status this[string gesture, Transform that] => LookAt(that) && Play(gesture);
public status this[string anim] => Play(gesture);
public status Face(Transform that, string anim = "Walk")
=> Playing(anim, θ.RotateTowards(that, rotationSpeed));
public status Face(Vector3 dir, string anim = "Walk")
=> Playing(anim, θ.RotateTowards(dir, rotationSpeed));
public status Give(Transform that, Actor recipient)
=> recipient.Has(that) || Reach(recipient.θ)
&& Playing("Idle", Offer(that, recipient))
&& Present(that);
public status Grab(Transform that) => Reach(that) && this["Grab"] && Hold(that).now;
public status Ingest(Transform that) => Reach(that) && this["Eat"] && Assimilate(that).now;
public status Idle => this["Idle"];
public status LookAt(Transform that, string rotationAnim = "Walk", string idleAnim = "Idle")
=> Face(that, rotationAnim) && this[idleAnim];
public status Push(Transform that) => Sequence()[
and ? Reach(that) && PushingSetup() :
and ? this["Push"] && PushingTeardown() : end
];
public status Strike(Transform that) => Reach(that) && this["Strike"];
public status Take() => (other == null) || Face(other.θ)
&& this["Take"] && Hold(gift).now;
public status Tell(Transform that, string msg) => Reach(that) && this["Tell"];
public status Throw(Transform that, Vector3 dir) => Sequence()[
and ? Hold(that) :
and ? Face(dir) && this["Throw"] + After(0.5f)?
[Impel(that, dir)] : end
];
public status Reach(Transform that, float dist = 1f)
=> Face(that) && Playing("Walk", θ.MoveTowards(that, dist, speed));
// ==============================================================
public bool IsLookingAt(Actor that) => θ.Look(that.θ) < 5f;
public bool Has(Transform that) => θ.Has(that);
// ==============================================================
action Assimilate(Transform that){ Destroy(that.gameObject); return @void(); }
action Hold(Transform that){
if (hold == null) throw new Ex("'hold' is null");
var body = that.GetComponent<Rigidbody>();
if (body) body.isKinematic = true;
that.SetParent(hold);
that.localPosition = holdOffset;
return @void();
}
action Impel(Transform that, Vector3 dir, float force = 10f){
that.SetParent(null);
var body = that.GetComponent<Rigidbody>();
body.isKinematic = false;
var F = dir.normalized * force;
body.AddForce(F, ForceMode.Impulse);
return @void();
}
status Offer(Transform that, Actor recipient)
=> Do(recipient.other = this).now
&& Do(recipient.gift = that).now
&& +(status)recipient.IsLookingAt(this);
status Present(Transform that) => Hold(that).now && this["Give"];
action PushingSetup(){
UseRootMotion(true);
foreach (Transform x in pushingBones){
var c = x.gameObject.AddComponent<SphereCollider>(); c.radius = 0.05f;
var b = x.gameObject.AddComponent<Rigidbody>(); b.isKinematic = true;
}
return @void();
}
action PushingTeardown(){
UseRootMotion(false);
foreach (Transform x in pushingBones){
Destroy(x.GetComponent<SphereCollider>());
Destroy(x.GetComponent<Rigidbody>());
}
return @void();
}
action UseRootMotion(bool flag)
=> Do( GetComponent<Animator>().applyRootMotion = flag );
}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment