26 February 2026

My Impressions of Zenva Courses

Article cover

As many of you know, on my X profile I usually share packs of assets, courses, and books that I find online at good prices. Some time ago, a pack of Zenva courses appeared on Humble Bundle. Based on what I had read in Reddit forums, I warned in the post that the quality of the courses might not be what people expected. To my surprise, Pablo Farias (@pablofariasnew), founder of Zenva, asked me to give his courses a chance because he didn’t believe they deserved that criticism. So I decided to buy the Humble Bundle pack and take several of the courses to see firsthand whether the impression I had formed from Reddit was accurate or not.

The pack I bought contained a lot of Godot courses. It also had some Unity courses I had purchased a long time ago but hadn’t been able to take. In the end, out of all of them, I completed four courses:

  • Tower Defender Game in Godot – Unit 1 – Base Game
  • Tower Defender Game in Godot – Unit 2 – Enhanced Towers
  • Intro to Visual Shaders in Godot 4
  • The Complete Procedural Terrain Generation Unity Course

The first two are just over an hour and a half long, the shader one is barely an hour, while the procedural terrain generation course in Unity spans more than three and a half hours. It’s a sample very similar to what Zenva courses usually are—or at least the ones I’ve obtained in my bundles—generally ranging from one to four or five hours.

To my surprise, I have to say I liked them a lot. All the courses are well structured and cover the scope they promise. They don’t go deep, but what they explain is enough for you to understand what’s going on and practice it confidently in the editor yourself. Even the theoretical concepts, although explained quickly, are conveyed clearly, leaving you with the right idea—perfectly valid for going deeper on your own afterwards.

Of course, they are all in English, but they include subtitles in multiple languages, including Spanish. From what I’ve seen, the Spanish subtitle translation is very good. Even so, I preferred to watch them with English subtitles. The instructors have very clean pronunciation and are easy to understand, so I only used subtitles to check specific words when I got distracted. With subtitles, you’ll have no trouble following the course, no matter your native language. Although it would be great if this platform—and the others that publish courses—started doing what YouTube does and also translated the audio using AI. I don’t know what the production cost is for that, but when you come across one of those, with translated audio, they’re delightful, because the voice even sounds natural.

I tried checking the price of individual courses, but apparently you only have the option to subscribe annually, which gives you access to the entire course catalog. That subscription seems to cost about $59.70 per year. As for whether the price is worth it, I couldn’t really say, because it depends on the value they bring you based on where you are in your learning journey. In my specific case, I’ve already moved past the phase of general introductory courses. I typically go for intermediate courses that cover specific topics. That makes me more selective, so I tend to avoid subscriptions like Zenva’s. But if you’re getting started, it may be a good option to pay that price and have all the courses concentrated and readily available, instead of bouncing around the internet looking for tutorials. You can also do what I did and keep an eye out for the bundles Zenva releases fairly often. That would let you access their content without paying for a subscription you might not get your money’s worth from if you don’t have time to watch courses regularly. If you follow me on X, I’ll let you know when I hear about a new bundle ;-)

To sum up: I liked the Zenva courses. They are good quality. The comments I had read on Reddit are not justified, at least in my opinion. Personally, I’m sure I’ll buy more bundles as they come out. I’m glad I was able to correct my mistake—there aren’t that many quality options to be discarding one incorrectly.

Analysis of the book Game AI Pro 360 – Guide to Architecture

Book cover
There are many books about artificial intelligence (AI), but not so many focused on its use in video game development. Among those, there are two types: introductory books and in‑depth ones. The one we are dealing with belongs to the second category. That’s why I don’t recommend it to anyone who hasn’t already sharpened their teeth on a good number of introductory books and tried implementing AI algorithms. Believe me, this book is not for starting to learn AI. In fact, none of the books in this collection are. With that warning out of the way, I’ll try to justify it by explaining what the book is about.

The book does not follow an overarching narrative. It will not guide you through a learning path. Instead, it is a compendium of expert articles, each with a format and level of detail very similar to academic papers. If you’ve ever had to process the RFC of a standard, the articles in this book will strongly remind you of that. The different articles focus on different implementations of decision‑making systems (finite state machines, behavior trees, task planners, etc.), although each approaches them differently.

It’s clear that the authors of each article are true experts. No one can dispute that. Each of them refers to implementations they have made in well‑known games. The problem is that, for whatever reason, most of the articles leave me with the feeling that the authors are holding back their best cards—that they’re not telling you everything. Sure, I imagine that a full explanation of the complete AI implementation for those AAA games wouldn’t fit in a book, let alone in a single article, but I finished the book with the impression that unless you are as much of an expert as the authors, you won’t be able to fill in the gaps they leave in their explanations. It’s a constant feeling of “Okay, I think I understand at a high level what you want to do, but how exactly is that implemented?”—and that’s where the article ends. It’s true that sometimes you get code snippets, but they tend to be fragments of interfaces or high‑level pseudocode.

I suppose we should at least be grateful that this book is a topic‑based compilation of the articles previously published in the earlier Game AI Pro series. At least the compilation has some thematic coherence. I didn’t read the older books, but if everything was mixed together, they must have been very confusing.

For all these reasons, I must warn you against this book if you are just entering the world of AI for video games. If that’s your case, I don’t think you’ll get anything useful from it. There are better options in which to invest your money and from which you will learn much more. I would only recommend this book to someone who has already been working professionally in this field for many years; and even then, I’m not sure whether the book’s content hasn’t already been surpassed by time.

11 February 2026

Creating Packages for Unity

Cover


Reusability is key in software development. Unity is no exception. After you’ve spent some time developing games, sooner or later you’ll come across problems you solved previously and you’ll want to reuse earlier implementations. It may also happen that a colleague needs a component you developed that would help them solve an implementation problem. In both cases, you’ll need to export a set of assets from a previous project so they can be easily imported into another. In this article, we’ll look at some ways to do that.

Direct Copy

The most obvious way to share components is to copy them onto a USB stick or into a ZIP package, and then copy them into the folder tree of the target project.

This approach has the advantage of simplicity. It’s immediate. But it has the disadvantage that it requires you to manually import each component, placing them in the correct folders. If the imported components have dependencies among themselves, it's easy for those dependencies to break if the components are imported into folders different from the originals.

Additionally, you must consider what exactly you want to copy. Many times the original files aren’t enough. When you include a file in a Unity project, the editor generates another file with a .meta extension where it stores parameters used in the process. Including .meta files in the copy is very important if you want to ensure that other developers use the exported assets in the same way you do.

Considering the above, the direct copy method is only advisable for personal copies—things you used in other projects, that you know well and know how they work, and therefore know how to “transplant” into another project. In all other cases, I recommend any of the other methods in this article—they will be cleaner and less error-prone.

Unity Package

The Unity editor allows creating a container package with the assets we choose and their dependencies. We can give this package to another colleague so they can import it from their editor.

Suppose we want to export a set of scripts we use for automated testing.

The scripts we want to export
The scripts we want to export

To create the package, simply right-click on any folder in the Project tab and select “Export as Asset Package...”.

A pop-up window will appear showing the entire folder tree of our project selected. In that window, you must uncheck everything except what you want to include in the exported package.

Export window
Export window

Once done, click Export, choose a name for the generated package (I named mine TestsCommonTools) and where to save it. The resulting file is what we will share with those we want to give our components to.

Generated Unity package
Generated Unity package

Now, let’s consider the perspective of the person who wants to import our components. They just need to drag the package into their Project tab for the import window to open. This window allows them to select which components to import, in case they don’t want them all.

Import window
Import window

When importing, we must keep in mind that the package’s folder structure will be added inside our Assets folder. This may not be a problem if we share the same folder standard used when the package was created—or it may be a problem if we don’t like that folder structure or if we already have folders with the same name but don’t want them “contaminated” with package content.

Folder structure before import
Folder structure before import

Folder structure after import
Folder structure after import

The good thing about Unity Packages is that the editor handles including meta files and various dependencies needed during import. The bad thing, as we’ve seen, is that our folder structure gets “polluted” by the standard used by the package creator. Therefore, this resource is only recommended occasionally or when sharing assets with team members who share your folder structure.

UPM Package

The evolution of Unity Packages is the packages for the Unity Package Manager (UPM). This is the modern and recommended system by Unity for managing packages, libraries, tools, shaders, samples, and functionalities in your projects.

It has many advantages over the previous system:

  • Packages can be installed and uninstalled from the Package Manager, simplifying the process and ensuring that uninstalling leaves no traces.
  • Installation occurs outside the Assets folder, keeping the project clean.
  • The Package Manager handles versions, making updates easy.
  • If a package depends on others, the Package Manager installs them as well.
  • Allows using official repositories (Unity), third-party ones (OpenUPM), or personal ones (GitHub).

To create a UPM package, open the Package Manager via Window > Package Management > Package Manager. In the pop-up, click the “+” icon in the top left and choose “Create package”.

Creating a UPM package via the Package Manager
Creating a UPM package via the Package Manager

A small window appears where you set the package name. In my example, I named it CommonTestTools.

It will then appear in the project’s package list.

Initial appearance of the package
Initial appearance of the package

However, everything shown at this point is provisional—you now need to configure it and add content.

When you click Locate, Unity will take you to the new package folder inside Packages.

Folder structure for our package
Folder structure for our package

As you can see in the previous screenshot, the Package Manager has already created a folder structure for our package. Each of these folders has a specific purpose, but depending on the purpose of our package, you may not need some of them. I’ll explain the function of each one:

  • Documentation: This is where you must place the help documentation for your package, in Markdown or HTML format.
  • Editor: This is where scripts containing editor extensions go, if your package includes any.
  • Runtime: This contains the scripts intended to be used by the game when it is running.
  • Samples: Usage examples of the package.
  • Tests: This folder should contain all tests (both unit tests and integration tests) to verify the correct functionality of your package. This folder, in turn, contains two subfolders: one for Editor and one for Runtime. The Editor one is used for testing utilities that use the Editor API. Aside from that case, the usual thing is to use the Tests/Runtime folder.

Of all the folders mentioned, the contents of the Runtime folder are the only ones that may end up in the final game if they are referenced from compiled code. The rest only make sense for editor use, so they do not contaminate the final game.

My example is somewhat particular, because these are tools meant to be used in the unit tests of a game—so, in principle, it doesn’t make sense for them to go into either the Runtime folder or the Editor folder at the root of the package. However, I found that I couldn’t get visibility of the tool’s classes from my PlayTests unless I placed them in the Runtime folder. So that’s what I ended up doing.

It is very important that we copy files using the Project tab of the Unity editor. This way, the editor will take care of copying not only the files but also their corresponding .meta files, which are essential for the package to function correctly.

Files placed in the package
Files placed in the package

With the package now filled with content, it’s time to define its metadata. This is done by editing the package.json file, located in the root folder of the package. The default contents of the package, as created by the Package Manager, look something like the following:

Default package.json content
Default package.json content

The purpose of the fields is very intuitive:

  • name: This is the full name of the package. It uses the reverse-domain-name format to avoid name collisions with other packages. In reality, the domain you use doesn’t matter as long as the full name doesn’t end up being the same as another package.
  • displayName: This is the short name that will be shown in the Package Manager and by which others will refer to your package.
  • version: The version of your package. It’s advisable to update it as you release new versions of the package, so that the Package Manager detects the change and suggests updates to the user.
  • unity: Version used to generate the package. It serves as an indicator of the minimum version compatible with the package.
  • unityRelease: The minor-version of the previous tag. Only necessary if, for whatever reason, your package only works starting from a specific patch.
  • description: A description of what your package does.
  • dependencies: All the packages that ours depends on to work. The Package Manager will install all those packages before installing ours.
  • author: Our information as the author of the package.
  • changelogUrl: The URL of our changelog. Typically, you would point this to the changelog of our repository.
  • documentationUrl: URL to the package documentation. It’s a good idea to point this to the README or wiki of the package’s repository.
  • licensesUrl: If you host your package on GitHub and have followed good practices, you’ve likely created a license file in your repository. This URL should point to it.

You don’t need to use all the fields. In fact, there are many more. These are the ones that the Package Manager introduces by default when creating the package. But you can use far fewer. For example, a package I created to have a measuring tape rule in the editor has the following package.json:

Contents of the package.json of my unity-measuring-tape package
Contents of the package.json of my unity-measuring-tape package

In the case of the package we are dealing with in our example, the following should be enough for now:

package.json for our example
package.json for our example

If we later upload the source code of our package to GitHub, we can always update the package.json by adding the corresponding fields that point to the repository.

The easiest way is to use the IDE to edit the package.json file, but Unity also lets you configure it from the editor. If you locate the package in the Package Manager, you’ll see that it offers you three buttons: Locate, Export, and Manage. We've already used the Export button. Now it’s time to click the Manage button, which will open a dropdown where you must choose the “Edit Manifest” option. This will open a window like this one in the inspector:

Editing the package.json from the Inspector
Editing the package.json from the Inspector

Once the changes are made, you may need to restart the editor for them to be reflected in the Package Manager.

We’re almost done. We still need to pay some attention to the .asmdef files. The Package Manager creates them in the directories where code may exist and links them to each other. In theory, you shouldn’t need to touch them because the default configuration is usually enough for simple cases. The problem is that the Package Manager names them using our Unity user ID, and it’s usually quite ugly. Even if we later change the package name in the package.json, the Unity editor does not regenerate the .asmdef files. So you have to search for those files in the different folders to rename them—both the file itself in the Project panel and the Name field of the .asmdef file in the inspector. What will happen when you do this is that links pointing to the renamed file from other .asmdef files will break. Therefore, once you’ve renamed all the .asmdef files, you’ll need to do a second pass to rebuild the links in the inspector of each file. It’s not complicated. You’ll see the broken link because the inspector highlights it, so you just need to add a new element to the list of references, choose the file with its new name, and remove the broken link entry. For example, the .asmdef file in the folder where I left the classes of my package ended up like this:

The .asmdef file of my package
The .asmdef file of my package

Generally speaking, keeping the “Auto Referenced” field checked can help avoid having to manually reference the asmdef from the asmdefs of the code that wants to use the tool’s classes. However, there may be cases in which, even with that, you still need to reference the package’s asmdef to use it from your code.

Another important thing to keep in mind is that the “Root Namespace” parameter of the asmdef must match the namespace used by the classes in our package. Otherwise, you might find that the user of the package cannot see its classes from their code.

With the above in place, the code of the project where we created the package will already be able to see its classes by importing through the namespace we defined in the asmdef.

Importing the classes of our package
Importing the classes of our package

Sharing a UPM package

With the above, we’ll now have a functional package, but it will only be usable in the project where we created it. The logical thing is that we want to export it so we can use it in other projects.

The most immediate way to export a UPM package is as a .tgz file. We just need to right-click the package folder inside Packages and choose “Export as UPM package…”. This will create a .tgz file that includes our package. Whoever receives the file will only need to import it from the Package Manager by clicking the “+” icon in the upper-left corner and choosing “Install package from tarball…”, which allows them to select the tgz file to load it.

The problem with the above option is that we’d be forced to send new tgz files to our users with each new version. A more versatile alternative is to upload the code of our package to GitHub. It’s enough for the root of the repository to be at the same level as the package.json file. By doing this, our users will be able to install the package using the “Install package from git URL…” option and providing the repository URL. The advantage of this approach is that if we change the version recorded in the package.json, the Package Manager will detect the change and notify the user that they can update.

Finally, you can also share your package by uploading it to a public repository like OpenUPM, to maximize its visibility. However, OpenUPM is used outside of the Package Manager, so it may deserve a separate article on its own.

Conclusion

In this article we have reviewed all the ways to reuse your Unity assets, either between your own projects or by sharing them with other developers. This should prevent you from being forced to “reinvent the wheel” by reimplementing components already present in other projects or manually copying their code, components, and dependencies between projects.