[RELEASED] Readme - A Rich Text Component Documentation Tool

Intro
This is a readme component for Unity, attachable to any GameObject as a component to document what you can’t in a script or the file system.

Similar Assets
There are a host of tools related to documentation but I’ve had trouble finding something for adding documentation via components. If you know of one feel free to post it!

This Asset
This project is meant to allow users the ability to better document Unity GameObjects as whole. Currently, the main ways yous can include documentation in your unity project are

  • With a readme in your file system
  • With comments in your code

This leaves a gap in the documentation. What do you do when your GameObject requires some simple notes that are not related to an individual script? Or what if you just really want to make sure others know why you’ve configured a component they way you have? We’ll now you can just whip a readme on it!

Example Usage
Here are some examples of how it works!

Edit Text

Apply Text Styles

Set Colors

Change Font Style/Size

Try It!
I still don’t have any fancy way to try it out. You can access the source code on GitHub!

A large chunk of that code was actually to fix a bug related to unity cursor placement in a RichText field.

Let me know what you think!

3 Likes

Update - Object Fields!

Hello! I’ve been toiling away and have made some progress on this readme editor. Since last post my main focus was to get object fields working. After I did that I spent a lot of time testing. For the last few days I’ve been doing nothing but bug fixes and I think we’re at a point where the tool is acceptable. There are still issues and it’s not perfect but we’ll get there! On to the update!

Object fields can now be added inline to the readme rich text.

Object Fields Example

After they are added they can be edited like any old rich text, you can copy/paste, update, delete, whatever.

The way it works is that when you drop an object field into the text, we add a tag that uses the objects instance Id to link back to the object:

That is what makes it copy/pasteable!

Next we find those tags in the text and draw object fields overtop of them. Then, when that object field is updated we update the text too. But we also still have to store the objects under the readme component so that Unity serializes the references when a project builds, or unity is closed.

Object Fields Example
Lastly we also support older version of unity. I’ve been testing in 5.6.4 and it’s working great there too.

Beta Testers?
If anyone is interested in trying the tool out for free I would certainly love someone to help me test and give feedback on anything and everything. If anyone is interested shoot me an email at mike@tinyphx.com!

Changes Since Last Post | GitHub

2 Likes

Update - Near Release!

Hi Everyone,

I am getting to the point where I am pretty confident in the quality of Readme. However, I still really need some others to try it out so I can make it even better. I am planning on putting it on the asset store soon but have made it available on the Tiny PHX website for free for a limited time before release.

You can download the unitypackage here!

Updates

Usability

Since last update I’ve done even more stability and user experience improvements. Most notably, the event.current was being consumed and use by the Unity TextEditor. I discovered this was happening when the active TextArea was updating and opened access to using some useful events before consumption.

Icons

  • Tack icon in scene for each Readme
  • Can be individually turned off in Advanced options
  • Can be bulk turned off in Advanced options

As always if you have any feedback I would love to hear!

Update - Redistributable!

Hi Everyone!

I’ve just published the first version of Readme to the Unity Asset Store.

Updates

Readonly Mode

There are now a couple of settings to control a readonly mode in the Advanced settings.

  • Readonly Mode - When enabled the edit button is hidden. This is great for distributing documentation that isn’t meant to be edited.
  • Disable All Readonly Mode - When enabled this forces all edit buttons to show. It’s useful if you have a lot of readonly Readmes to edit.

If readonly mode is enabled you have no way to get to the advanced menu to turn it off so I’ve added a shortcut:

  • Alt+a - toggles Advanced options (even in readonly mode)

Here is what it looks like in Readonly mode:

Compared to the normal view:

Supports Redistribution

Readme now uses a configuration file for the settings. This allowed me to create a redistributable version without creating a whole new asset. Each one just comes with a different settings file. Yay for simplicity!

Wow! Thanks for the great work :slight_smile: This looks excellent and is really helpful! Thanks so much for sharing!

I was wondering if you could add the “Undo” feature?
cuz somehow, it is occasionally highlighted the whole document and I accidentally press spacebar which led to clear the whole documents.
And I couldn’t undo it afterward.
This is a great asset for documenting your project

EDIT: also could you please investigate highlighting the whole document issue whenever we click something inside the text box?

It is very irregular, sometimes it is highlighting, and sometimes is not, kinda random.
Let’s say you type a couple of lines, and you want to correct the above line, so you use your mouse and click the above line and it highlighting everything.

Sometimes it is highlighting everything when you press enter (New Line), which happened to me a couple of times, but I’m unable to repro it.

Hi, thank you for a nice tool :slight_smile:

For some reason, it make unity crash when i add the component Readme, on 2019 and 2020. But on 2021.2 it doesn’t crash but have this red error:

StackOverflowException: The requested operation caused a stack overflow.
UnityEngine.SceneManagement.Scene.get_name () (at :0)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:75)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate, System.Boolean& found) (at :0)
System.Linq.Enumerable.FirstOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeManager.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
TP.Readme.ConnectManager () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:85)
TP.Readme.get_ObjectIdPairs () (at Assets/Packages/TP/Readme/Assets/Scripts/Readme.cs:154)
TP.ReadmeManager+<>c.<get_ObjectIdPairs>b__9_0 (TP.Readme item) (at Assets/Packages/TP/Readme/Assets/Scripts/ReadmeManager.cs:95)
System.Linq.Enumerable.TryGetFirst[TSource] (System.Collections.Generic

The undo feature is working in the latest version for anyone wondering. I took a lengthy hiatus from being a productive member of the comunity. Getting back into things and will do my best to support this and other assets moving forward.

1 Like

This is also fixed in the latest version. Thanks for your report. It did help to narrow things down. Appreciate it!

1 Like

Hi anyone who makes their way to this thread! I’ve been out of commishion for a while but for the first time in about a decade I am back to part time contract work, leaving time for me to better suport tools and get back to game dev. Hope everyone has been well.

The first thing I worked on was getting Readme upto date with latest versions of unity and making it more stable. Been really kicking butt on this thing since May and am finally at the point of publishing an update I am proud of. Check out the changes here:

Here’s a video of the latest in action. The update is mostly the addition of scroll support and tons of bug fixes and quality of life refactors:

Lastly I am publishing a free version right now. It will be out for approval today! This should make it really easy to distribute assets on the store that use Readme. The only difference in the free version is a promt that is shown to the user once a week, only if they are editing readmes. It’s similar to the free version of sublime.

2 Likes

This is such a cool thing!
Finally no more central document that grows out of hand and it looks a ton better than “sticky notes” and similar assets.

Btw. would it be feasible to support ScriptableObjects too somehow?

1 Like

Woah, this looks awesome! The ability to add things like references is super duper cool <3

1 Like

I can add ScriptableObjects to the list of things to look into. I had thought of something similar that may work for ScriptableObjects too. I think it would be neat to add an attribute that allows you to add docs right above a field in a unity component, or maybe as a popup. I think something like that should work with ScriptableObjects.

Thanks for checking it out!

1 Like

Hi Everyone,

Today we published a free version of Readme. Check it out and let me know if you have any feedback!

I get this error right after adding the Readme component

DirectoryNotFoundException: Could not find a part of the path "C:\Users\prduq\AppData\LocalLow\Studios Corp_\Adventure \readme\Adventure\Settings_PopUpDate.json"
System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.IO.FileOptions options) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
(wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int,System.IO.FileOptions)
System.IO.StreamWriter..ctor (System.String path, System.Boolean append, System.Text.Encoding encoding, System.Int32 bufferSize) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
System.IO.StreamWriter..ctor (System.String path) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
(wrapper remoting-invoke-with-check) System.IO.StreamWriter..ctor(string)
System.IO.File.WriteAllText (System.String path, System.String contents) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
TP.ReadmeSettings.SaveSettings () (at Assets/Packages/TP/Readme/Runtime/Settings/ReadmeSettings.cs:73)
TP.ReadmeSettings.CreateDefaultSettings () (at Assets/Packages/TP/Readme/Runtime/Settings/ReadmeSettings.cs:62)
TP.ReadmeSettings.LoadAllSettings () (at Assets/Packages/TP/Readme/Runtime/Settings/ReadmeSettings.cs:79)
TP.Readme.UpdateSettings (System.Boolean force, System.Boolean verbose) (at Assets/Packages/TP/Readme/Runtime/Readme.cs:211)
TP.ReadmeEditor.OnInspectorGUI () (at Assets/Packages/TP/Readme/Editor/ReadmeEditor.cs:82)
UnityEditor.UIElements.InspectorElement+<>c__DisplayClass59_0.<CreateIMGUIInspectorFromEditor>b__0 () (at <46976ad9004e4c8ca11353e8bb94e264>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

EDIT: Fixed it by removing period character from savePath in Readme.cs

string saveLocation = (Application.persistentDataPath + "/readme/" + PlayerSettings.productName);
// remove periods from saveLocation
saveLocation = saveLocation.Replace(".", "");

Hi, I tested the free version and here are some ideas to improve it:

  • http link opening in browser
  • changing text size of selection only instead of whole text
  • scriptable object version to comment folders, with a look like Unity’s own ReadmeEditor seen when opening its projects templates.

Also I see this error when clicking Edit or Done, but does not seem to impact usage:

InvalidOperationException: Sequence contains more than one matching element
System.Linq.Enumerable.SingleOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at <93223d662c2546d4b5d1784737504095>:0)
TP.ReadmeUtil.g__GetEditorWindow|5_0 (System.String editorWindowTitle) (at Assets/Plugins/Readme/Editor/ReadmeUtil.cs:58)
TP.ReadmeUtil.FocusEditorWindow (System.String windowTitle) (at Assets/Plugins/Readme/Editor/ReadmeUtil.cs:49)
TP.ReadmeTextArea.g__UpdateFocus|80_1 () (at Assets/Plugins/Readme/Editor/ReadmeTextArea.cs:257)
TP.ReadmeTextArea.Update () (at Assets/Plugins/Readme/Editor/ReadmeTextArea.cs:204)
TP.ReadmeEditor.AfterOnInspectorGUI () (at Assets/Plugins/Readme/Editor/ReadmeEditor.cs:153)
TP.ReadmeEditor.OnInspectorGUI () (at Assets/Plugins/Readme/Editor/ReadmeEditor.cs:138)
UnityEditor.UIElements.InspectorElement+<>c__DisplayClass59_0.b__0 () (at <77cfaa957c26445e8d2fa87bf3ff3fa6>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

Hi, great asset. Love the ability to add references!

It has the following error when click on a prefab (nested prefab) having the Readme Component:

nvalidOperationException: Sequence contains more than one matching element
System.Linq.Enumerable.SingleOrDefault[TSource] (System.Collections.Generic.IEnumerable1[T] source, System.Func2[T,TResult] predicate) (at :0)
TP.ReadmeUtil.g__GetEditorWindow|5_0 (System.String editorWindowTitle) (at Assets/Packages/TP/Readme/Editor/ReadmeUtil.cs:58)
TP.ReadmeUtil.FocusEditorWindow (System.String windowTitle) (at Assets/Packages/TP/Readme/Editor/ReadmeUtil.cs:49)
TP.ReadmeTextArea.g__UpdateReturnFocus|80_3 () (at Assets/Packages/TP/Readme/Editor/ReadmeTextArea.cs:284)
TP.ReadmeTextArea.Update () (at Assets/Packages/TP/Readme/Editor/ReadmeTextArea.cs:205)
TP.ReadmeEditor.AfterOnInspectorGUI () (at Assets/Packages/TP/Readme/Editor/ReadmeEditor.cs:153)
TP.ReadmeEditor.OnInspectorGUI () (at Assets/Packages/TP/Readme/Editor/ReadmeEditor.cs:138)
UnityEditor.UIElements.InspectorElement+<>c__DisplayClass59_0.b__0 () (at :0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

@DavidLe360 Thanks for letting me know. This could be an issue with the nested prefabs but could also just be somehow a second Readme component was attached to a single GameObject. If you want to change the code now, updating “SingleOrDefault” to “FirstOrDefault” in this file “Assets/Packages/TP/Readme/Editor/ReadmeUtil.cs” on line 58 might do the trick. I’ve added that on my side but need to investigate a little more. I’ll make sure this go out with the next update.

Thanks again for the heads up! I check our support Discord more frequently if you’d like to hop in there. Also, if you don’t feel comfortable making the code edit I can send you the update there in a Unity Package.

Support Discord: Tiny PHX

1 Like