---
title: "unifir 103 - Using Assets"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{unifir 103 - Using Assets}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

This vignette supplements 
[unifir 101](unifir-user-guide.html)
and 
[unifir 102](unifir-dev-guide.html)
to get into the weeds of how you can add assets --
which is to say, any sort of object or event that isn't specifically
provided by the Unity engine itself -- 
into your Unity scenes. 
If you're trying to build scenes with unifir, I recommend checking out
unifir 101 first; if you're looking to extend unifir, I recommend reading both
the other vignettes to start. This vignette will be a bit shorter than the other
two, focused entirely on how to import and instantiate assets in your world.

## Importing Assets

An "asset" in Unity is a really vague category -- it's any item you're including
in a scene, be it 3D models, code, audio, or really any other type of data. 
To get away from this vagueness, unifir uses a slightly more pragmatic 
definition: an asset is any file or directory you want to include in your
Unity project.

Unity provides a neat format for moving collections of assets around, allowing
you to compress folders into "unitypackage" files which can be imported into
other projects. Unfortunately, importing these packages using Unity's batchmode
API currently does not work (and hasn't worked for a number of years).
So rather than deal with this format and Unity's tools for moving data around,
unifir just copies asset files directly into your project when running scripts
through `action()`.

That's where the function `import_asset()` comes in. This function takes two 
main arguments: the script to add the prop to and the path to the asset to copy 
(either a single file or a directory, to copy recursively). For instance, 
let's say we want to import all of the files stored at `example_asset`:

```{r}
example_asset <- tempfile()
file.create(example_asset)
```

We can import that using `import_asset()` as follows:

```{r}
library(unifir)
script <- make_script(
  project = file.path(tempdir(), "unifir"),
  unity = waiver() # Makes it so make_script won't error if it can't find Unity
)

script <- import_asset(script, example_asset)
```

(For more information on `waiver()`, check out unifir 102).

Now when we run `action()` on this script, we'll copy `example_asset` directly
into the `Assets` folder of our Unity project. Note that this is done entirely 
in R, using `file.copy(..., recursive = TRUE)`, which has two main implications:
first, this copy step won't be present in your C# code anywhere, and secondly
the original file structure will be preserved if `example_asset` points to a 
directory.

That second point is particularly important when it comes to actually using 
these objects in a scene, rather than just having them exist in your project.
To talk about that, we should move along to:

## Instantiating Prefabs

There are a lot of ways to actually bring assets into a Unity scene as things 
that users will interact with or otherwise be affected by in your environment.
The easiest one of those to work with, which is the only one unifir puts much
thought into, is referred to as a "prefab". A prefab is a Unity GameObject 
that incorporates external data and code, stored as a single file; 
for more information on prefabs and how to use them I'd recommend the official 
[Unity documentation](https://docs.unity3d.com/Manual/Prefabs.html).
For our purposes, I'm going to assume you've already got a prefab created and 
you want to import it into your scene.

The first step in doing so is to use `import_asset()` in order to bring your 
prefab _file_ (along with all the external files it relies on) into the Unity 
project. In order to turn that file into an actual object in the environment, 
we can use the `instantiate_prefab()` function from unifir.
This function can work with just two arguments (though there are more, 
documented in `?instantiate_prefab`): the script object and the path to the 
prefab you want to instantiate.

Importantly, that path is relative to the Unity project root directory, _not_
your current working directory. Since we used `import_asset()` to import our
"asset" earlier, that means our asset is inside the "Assets" directory inside
our Unity project, and we can instantiate it as follows:

```{r}
script <- instantiate_prefab(script,
                             prefab_path = file.path("Assets", 
                                                     basename(example_asset)))
```

If you used `import_asset()` to import a directory, the file structure of your
directory will be preserved. That means that, if `example_asset` were a 
directory containing a prefab at `sub_directory/example.prefab`, we'd set
`prefab_path = Assets/example_asset/sub_directory/example.prefab` instead.

We can use the other arguments to `instantiate_prefab()` to customize our object
further, specifying its location, rotation, and scaling as desired.

## Making it Easier

Because prefabs can exist at different locations in imported assets, and a 
single asset directory can contain multiple prefabs, unifir can't automatically
infer what prefab you're trying to create with `instantiate_prefab`.
That means every time you want to add GameObjects to a scene, you need to 
go through this two-step process with `import_asset` and `instantiate_prefab`,
specifying the path to the asset to import and then the path to the prefab 
itself.

For a small set of objects, however, `unifir` makes things a bit easier. 
A collection of permissively-licensed assets at 
[https://github.com/mikemahoney218/unity_assets/](https://github.com/mikemahoney218/unity_assets/)
can be automatically added to the scene using the helper functions
`add_default_player` and `add_default_tree`.
Those functions will handle downloading assets, importing them into Unity, and
instantiating the prefabs, making it easy to add player controllers and 3D trees
to your scene. These objects are also all permissively licensed -- the 
controllers are currently all MIT-licensed, while the trees are CC-0 1.0 --
making them free to use in any of your projects.

The functions -- which I'm wrapping here in `if (interactive())` to prevent
them from downloading files on CRAN -- take the same arguments as
`instantiate_prefab` to let you specify position, scale, and rotation of your
objects, but handle all the file path trickiness for you:

```{r}
if (interactive()) {
  script <- add_default_player(script)
  script <- add_default_tree(script, "tree_1")
}
```

If you have any (permissively-licensed -- no GPL or CC-BY) assets you'd like to
share as part of this set, 
[open an issue on GitHub!](https://github.com/mikemahoney218/unity_assets/issues)
