(log & args)
Log message to the Unity console. Arguments are combined into a string. See Also: Unity Console
(null->nil x)
Same as identity
, except if x
is a null UnityEngine.Object
, will return
nil
.
(null? x)
Should x
be considered nil
? (null? x)
will evalute to true
if x
is
in fact nil
, or if x
is a UnityEngine.Object
instance such that
(UnityEngine.Object/op_Equality x nil)
returns true
. Otherwise will
return false
.
(instantiate original)
(instantiate original position)
(instantiate
original position rotation)
Clones the original object and returns the clone. The clone can optionally be given a new position or rotation as well.
Wraps =Object/Instantiate=.
(create-primitive prim)
(create-primitive prim name)
#### Description
Creates a game object with a primitive mesh renderer and appropriate
collider. prim
can be a =PrimitiveType= or one of :sphere
:capsule
:cylinder
:cube
:plane
:quad
. If supplied, the third argument should
be a string, and will be set as the name of the newly created GameObject.
Wraps =GameObject/CreatePrimitive=.
(destroy obj)
(destroy obj t)
Removes a GameObject, component or asset. When called with t
, the removal
happens after t
seconds. Wraps =Object/Destroy=.
(destroy-immediate obj)
Removes a GameObject, component or asset immediately. Wraps =Object/DestroyImmediate=.
(retire obj)
If in Play mode, calls =Object/Destroy=, otherwise calls =Object/DestroyImmediate=.
(object-typed t)
Returns one live instance of UnityEngine.Object subclass type t
from the
scene graph, or nil
if no such object can be found. Wraps
=Object/FindObjectOfType=.
(objects-typed t)
Returns a sequence of all live instances of UnityEngine.Object subclass type
t
in the scene graph. Wraps =Object/FindObjectsOfType=.
(object-named name-or-regex)
Returns one live GameObject from the scene graph, the name of which matches
name-or-regex
. name-or-regex
may be a string or a regular expression
object.
(objects-named name-or-regex)
Returns a sequence of all live =GameObject=s in the scene graph, the name of
which match name-or-regex
. name-or-regex
may be a string or a regular
expression object.
(object-tagged t)
Returns one live =GameObject= tagged t
from the scene graph, or nil
if no
such GameObjects exist.
Wraps =GameObject/FindWithTag=.
(objects-tagged t)
Returns a sequence of live =GameObject=s tagged tag. Returns empty array if no =GameObject= was found. Wraps =GameObject/FindGameObjectsWithTag=.
(gobj x)
Coerces x
, expected to be a GameObject or Component, to a corresponding
live (non-destroyed) GameObject instance or to nil
by the following policy:
- If
x
is a live GameObject, returns it. - If
x
is a destroyed GameObject, returnsnil
. - If
x
is a live Component, returns its containing GameObject. - If
x
is a destroyed Component, returnsnil
. - If
x
isnil
, returnsnil
. - Otherwise throws an ArgumentException.
(child+ x child)
(child+ x child world-position-stays)
#### Description
Makes GameObject x
the new parent of GameObject child
. Returns child
.
If world-position-stays
is true, child
retains its world position after
being reparented.
(child- x child)
(child- x child world-position-stays)
#### Description
Removes GameObject x
as the parent of GameObject child
, moving child
to
the top of the scene graph hierarchy. Returns nil
.
If world-position-stays
is true
, child
retains its world position after
being reparented.
(children x)
Gets the live children of GameObject x
as a persistent vector of
GameObjects.
(parent x)
Returns the live parent of GameObject x
or nil
if it has none.
GameObjects at the top of the hierarchy do not have parents.
(cmpt x t)
Returns the first live Component of type t
attached to GameObject x
.
Returns nil
if no such Component is attached.
(cmpts x t)
Returns all live Components of type t
attached to GameObject x
as a
(possibly empty) array.
(cmpt+ x t)
Adds a new Component of type t
to GameObject x
. Returns the new
Component.
(cmpt- x t)
Removes every Component of type t
from GameObject x
. Returns nil
.
(ensure-cmpt x t)
If GameObject x
has a component of type t
, returns it. Otherwise, adds a
component of type t
and returns the new instance.
macro
(with-cmpt gob bindings & body)
#### Description binding => name
component-type
For each binding, binds name
to an instance of class component-type
attached to GameObject gob
. If no such instance is currently attached to
x
, a new instance of component-type
will be created, attached to x
, and
bound to name
. body
is then evaluated in the lexical context of all
bindings.
macro
(if-cmpt gob [cmpt-name cmpt-type] then & else)
If a component of type cmpt-type
is attached to GameObject gob
, binds it
to cmpt-name
, then evaluates and returns then
in the lexical scope of
that binding. Otherwise evaluates and returns else
, if provided, or returns
nil
if else
is not provided.
macro
(sets! o & assignments)
Set multiple fields or properties on an object instance o
simultaneously.
assignment => field-name value
For each assignment, field-name is the name of a field or property of o
,
and value
is the new value it will be set to.
Returns the final set value.
(sets! (.transform some-game-object) position (arcadia.linear/v3 1 2 3) localScale (arcadia.linear/v3 1 2 3))
macro
(set-with! obj [name prop :as bindings] & body)
#### Description Access and
set a field or property prop
on object instance obj
. The new value at (.
obj prop)
will be set to the value of body
, evaluated in an implicit do
,
with name
bound to the preexisting value of (. obj prop)
. This operation
is not atomic, and should be used with caution in concurrent contexts.
As an example,
(set-with! (.transform some-game-object) [pos position] (arcadia.linear/v3+ pos (arcadia.linear/v3 1 0 0)))
is equivalent to
(let [tr (.transform some-game-object) pos (.position tr)] (set! (.position tr) (arcadia.linear/v3+ (.position tr) (arcadia.linear/v3 1 0 0))))
Since the object is the first argument, multiple such assignments on an
object may be chained using doto
. Returns the new value of the field or
property.
(descendents x)
Returns a sequence containing all descendents of GameObject x
in
depth-first order. The descendents of x
are all GameObjects attached as
children to x
in the Unity hierarchy; all of those GameObject’s children;
and so on.
(available-hooks)
Returns a sorted seq of all permissible hook event keywords.
(hook+ obj event-kw k f)
Attach a Clojure function, preferrably a Var instance, to GameObject obj
on
key k
. The function f
will be invoked every time the event identified by
event-kw
is triggered by Unity.
f
must be a function of 2 arguments, plus however many arguments the
corresponding Unity event function takes. The first argument is the
GameObject obj
that f
is attached to. The second argument is the key k
it was attached with. The remaining arguments are the arguments normally
passed to the corresponding Unity event function.
Returns f
. #### See Also * Unity Event Functions
(hook- obj event-kw key)
Removes hook function from GameObject obj
on the Unity event corresponding
to event-kw
at key
, if it exists. Reverse of
(hook+ obj event-kw key hook-function)
Returns nil
.
(clear-hooks obj event-kw)
Removes all hook functions on the Unity event corresponding to event-kw
,
regardless of their keys.
(hook obj event-kw key)
Retrieves an attached hook function from GameObject obj
. event-kw
is a
keyword specifying the Unity event of the hook function, and key
is the key
of the hook function.
In other words, retrieves any hook function attached via
(hook+ obj event-kw key hook-function)
or the equivalent.
(snapshot x)
Converts defmutable
instance x
to a persistent representation.
(maybe-snapshot x)
Unstable implementation detail, please don’t use.
(mutable x)
Given a persistent representation of a mutable datatype defined via
defmutable
, constructs and returns a matching instance of that datatype.
Roundtrips with snapshot
; that is, for any instance x
of a type defined
via defmutable
,
(= (snapshot x) (snapshot (mutable (snapshot x))))
(maybe-mutable x)
Unstable implementation detail, please don’t use.
(lookup go k)
Returns the state of GameObject go
at key k
. Does not convert defmutable
instances to persistent representations.
(state go)
(state go k)
With one argument, returns the state of GameObject go
on all keys as a map.
With two arguments, returns the state of GameObject go
at key k
. If this
state is a defmutable
instance, will return a persistent representation
instead. To avoid this behavior use lookup
.
(state+ go k v)
Sets the state of GameObject go
to value v
at key k
. Returns v
. If
v
is a persistent representation of a defmutable
instance, will convert
it to a mutable instance before inserting in the scene graph.
(state- go k)
Removes the state of object go
at key k
.
(clear-state go)
Removes all state from the GameObject go
.
(update-state go k f)
(update-state go k f x)
(update-state go k f x y)
(update-state go k f x y z)
(update-state go k f x y z & args)
Updates the state of GameObject go
at key k
with function f
and
additional arguments args
. Args are applied in the same order as . Returns
the new value of the state at k
.
In the special case that the value in state is a defmutable instance, f
will be applied to the persistent representation of that value, which will
then be converted to a mutable instance again, and inserted into state at
k
. The returned value will be f
applied to the persistent representation.
(role- obj k)
Removes a role from GameObject obj
on key k
. Any hook or state attached
to obj
on key k
will be removed. Returns nil
.
(role+ obj k r)
Adds a role r
to GameObject obj
on key k
, replacing any previous role
on k
. Keys in r
corresponding to Unity event functions, such as
:update
, :on-collision-enter
, etc, are expected to have values meeting
the criteria for hook functions described in the docstring for hook+
. For
such a key event-kw
, values will be attached to obj
as though by (hook+
obj event-kw k (get r event-kw))
.
If present, the value of the key :state
in r
will be attached to obj
as
though by (state+ obj k (get r :state))
.
For example,
(role+ obj, :example-role, {:state 45, {:update #'on-update, :on-collision-enter #'on-collision-enter}})
has the same effect as
(role- obj :example-role) (state+ obj :example-role 45) (hook+ obj :update :example-role #'on-update) (hook+ obj :on-collision-enter :example-role #'on-collision-enter)
As with state+
, persistent reprsentations defmutable
data as values in
:state
will be converted to mutable instances.
Returns r
.
(roles+ obj rs)
Takes a GameObject obj
and map rs
containing role keys and role maps as
entries. For each entry in rs
with key k
and value r
, adds r
to obj
on key k
as though calling
(role+ obj k r)
Returns rs
.
(roles- obj ks)
Takes a GameObject obj
and collection of keys ks
. For each key k
in
ks
, will remove k
from obj
, as if calling
(role- obj k)
Returns nil
.
(role obj k)
Returns a map of all hooks and state attached to GameObject obj
on key k
.
Within the returned map, keys will be either hook event keywords such as
:update
, :on-collision-enter
, etc, or :state
.
(hook+ obj :update :test #'on-update) (state+ obj :test {:speed 3, :mass 4}) (role obj :test) ;; returns: ;; {:state {:speed 3, :mass 4}, ;; :update #'on-update}
(roles obj)
Returns a map containing all the roles attached to GameObject obj
. For each
entry in this map, the key is the key of some hooks or state attached to
obj
, and the value is the map one would get by calling (role obj k)
for
that key k
. For example:
(hook+ obj :update :key-a #'on-update) (state+ obj :key-a {:speed 3, :mass 4}) (hook+ obj :update :key-b #'other-on-update) (state+ obj :key-b {:name "bob", :health 5}) (roles obj) ;; returns: ;; {:key-a {:state {:speed 3, :mass 4}, ;; :update #'on-update}, ;; :key-b {:state {:name "bob", :health 5}, ;; :update #'other-on-update}}
Roundtrips with roles+
.
macro
(defrole name entry*)
Macro for defining roles quickly. Each entry can be either a key-value pair with a keyword key, such as would normally occur in a map intended as an Arcadia role, or an inlined function definition.
Normal key-value pairs get inserted into the generated map. For example,
(defrole movement :state {:speed 3} :update #'movement-update)
will expand into
(def movement {:state {:speed 3} :update #'movement-update})
Inlined function definitions have the following syntax:
(name [args*] body)
name must be the symbol form of an Arcadia hook keyword. A function intended
for the :update
hook, for example, should have the name update
:
(defrole movement :state {:speed 3} (update [obj k] ...))
Each inlined function definition will generate a var, with a name
constructed as follows: <name of role>-<name of hook>
For example, the movement
role above will generate a var named
movement-update
bound to a function with the provided arguments and body,
and include that var in the generated role map, expanding into something
like:
(do (defn movement-update [obj k] ...) (def movement {:state {:speed 3} :update #'movement-update}))
Note that generating vars is usually a bad idea because it messes with tooling and legibility. This macro does it anyway because the hook functions should serialize in the Unity scene graph, and that requires vars.
(mut! x kw v)
Dynamically sets field keyword kw
of defmutable
instance x
to new value
v
. Returns v
.
(delete! x k)
Removes dynamic entry k
from defmutable
instance x
.
macro
(defmutable [name [fields*] other*])
Defines a new serializable, type-hinted, mutable datatype, intended for
particularly performance or allocation sensitive operations on a single
thread (such as Unity’s main game thread). These datatypes support
snapshotting to persistent data via snapshot
, and reconstruction from
snapshots via mutable
; snapshotting and reconstructing are also integrated
into state
, state+
, update-state
, role
, role+
, and roles
.
defmutable
instances may be mutated in two ways. Their fields may be
mutated directly using set!
and dot syntax. Fields may also be dynamically
set using (mut! obj k v)
. Here, obj
is the defmutable
instance, k
is
the keyword key for an entry, and v
is the new value of that entry to set
on the defmutable instance.
Instances of these types may be converted into persistent representations and
back via snapshot
and mutable
. This roundtrips, so if x
is such an
instance:
(= (snapshot x) (snapshot (mutable (snapshot x))))
If a persistent snapshot is specified as the state argument of set-state
,
or as the :state
value in the map argument of role+
, the ArcadiaState
component will be populated at the appropriate key by the result of calling
mutable
on that snapshot. Conversely, role
and roles
will automatically
convert any mutable instances that would otherwise be the values of :state
in the returned map(s) to persistent snapshots.
defmutable
supports four special options to help define custom snapshot
and mutable
implementations:
:snapshot
:mutable
:snapshot-elements
:mutable-elements
:snapshot
and :mutable
expect their values to be in the following form:
([this-param key-param value-param] body*)
When calling snapshot
or mutable
, the function defined by :snapshot
or
:mutable
will be called on each entry in the defmutable
instance (in the
case of snapshot
) or the persistent map representation (in the case of
mutable
). When these functions run, this-param
will be assigned to the
original defmutable
instance for snapshot
, or to the original persistent
map representation for mutable
; key-param
will be assigned to the keyword
key of this entry; and val-param
will be assigned to its incoming value.
For :snapshot
, the return will be the value of the corresponding entry in
the persistent map representation. For :mutable
, the return will be the
value of the corresponding entry in the defmutable
instance representation.
:snapshot
and :mutable
should invert each other.
:snapshot-elements
and :mutable-elements
support finer specialization of
snapshot
and mutable
behavior. They expect their values to be maps from
keyword names of possible entries, to the same sort of function
specifications taken by :snapshot
and :mutable
. Specifications made with
:snapshot-elements
or :mutable-elements
take priority over those made
with :snapshot
or :mutable
.
See the online documentation for examples.
defmutable
will automatically generate a constructor function. As with
deftype
, the name of its var will be ->
followed by the name of the type,
and its expected arguments will be the initial values of fields
, in order.
For example, given the following defmutable
definition:
(defmutable Sheep [wooliness bouyancy])
an instance of Sheep
could be constructed using
(->Sheep 3 4)
defmutable
serialization, via either snapshot
or Unity scene-graph
serialization, does not currently preserve reference identity. Calling
mutable
on the same snapshot twice will result in two distinct instances.
It is therefore important to store any given defmutable
instance in just
one place in the scene graph.
Since they define new types, reevaluating defmutable
forms will require
also reevaluating all forms that refer to them via type hints (otherwise
they’ll fall back to dynamic lookups). defmutable-once
is like
defmutable
, but will not redefine the type if it has already been defined
(similar to defonce
).
As low-level, potentially non-boxing constructs, instances of defmutable
types work particularly well with the magic
library.
macro
(defmutable-once & [name :as args])
Like defmutable
, but will only evaluate if no type with the same name has
been defined.