Friday, November 10, 2017
Friday, September 15, 2017
Avoid FindObjectsOfType with this Pattern
public class SomeComponent : MonoBehaviour { public static List<SomeComponent> Instances = new List<SomeComponent>(); private int instanceIndex = -1; void OnDisable() { var lastIndex = Instances.Count - 1; Instances[instanceIndex] = Instances[lastIndex]; Instances[instanceIndex].instanceIndex = instanceIndex; Instances.RemoveAt(lastIndex); } void OnEnable() { Instances.Add(this); instanceIndex = Instances.Count - 1; } }
Tuesday, August 22, 2017
Vector3.sqrMagnitude vs Vector3.magntiude
sqrMagnitude is 20% faster than magnitude.
magnitude: 0.862013
srqMagnitude: 0.689175
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Diagnostics; public class MagVsSqrMag : MonoBehaviour { void Start() { var C = 10000000f; var sw = new Stopwatch(); var vec = new Vector3(Random.value, Random.value, Random.value); var r = 0f; for (var i = 0; i < C; i++) { sw.Start(); r += vec.magnitude; sw.Stop(); } UnityEngine.Debug.Log("magnitude:" + (sw.ElapsedTicks / C)); sw.Reset(); vec = new Vector3(Random.value, Random.value, Random.value); for (var i = 0; i < C; i++) { sw.Start(); r += vec.sqrMagnitude; sw.Stop(); } UnityEngine.Debug.Log("srqMagnitude:" + (sw.ElapsedTicks / C)); UnityEngine.Debug.Log(r); } }
Monday, February 13, 2017
Take a Unity Screenshot with Alpha
This script takes a screenshot and saves it to the user desktop. It has options to use an alpha background, and also upscale the image. Useful for taking pictures of a scene or model for composition by artists.
using UnityEngine; using System.IO; using System; [RequireComponent (typeof(Camera))] public class CaptureWithAlpha : MonoBehaviour { public int UpScale = 4; public bool AlphaBackground = true; Texture2D Screenshot () { var camera = GetComponent<Camera> (); int w = camera.pixelWidth * UpScale; int h = camera.pixelHeight * UpScale; var rt = new RenderTexture (w, h, 32); camera.targetTexture = rt; var screenShot = new Texture2D (w, h, TextureFormat.ARGB32, false); var clearFlags = camera.clearFlags; if (AlphaBackground) { camera.clearFlags = CameraClearFlags.SolidColor; camera.backgroundColor = new Color (0, 0, 0, 0); } camera.Render (); RenderTexture.active = rt; screenShot.ReadPixels (new Rect (0, 0, w, h), 0, 0); screenShot.Apply (); camera.targetTexture = null; RenderTexture.active = null; DestroyImmediate (rt); camera.clearFlags = clearFlags; return screenShot; } [ContextMenu ("Capture Screenshot")] public void SaveScreenshot () { var path = Environment.GetFolderPath (Environment.SpecialFolder.Desktop); var filename = "SS-" + DateTime.Now.ToString ("yyyy.MM.dd.HH.mm.ss") + ".png"; File.WriteAllBytes (Path.Combine (path, filename), Screenshot ().EncodeToPNG ()); } }
Friday, February 03, 2017
Building fast, quality network server programs with Go.
I've been investigating and learning Go. There is a lot of high quality tools out there, for example:
- xo generates types and functions to match your SQL schema, and
- goa lets you design a REST api using a DSL, then generate the code to implement that API!
Compile time for Go is super fast, and so is the built executable. I'm using vim for the IDE, and it has excellent support for Go, including autocompletion which is great when you're learning the language.
- xo generates types and functions to match your SQL schema, and
- goa lets you design a REST api using a DSL, then generate the code to implement that API!
Compile time for Go is super fast, and so is the built executable. I'm using vim for the IDE, and it has excellent support for Go, including autocompletion which is great when you're learning the language.
Wednesday, January 25, 2017
A HTTP server embedded inside Unity3D.
Just 514 lines of code. Uses sockets only, no other dependencies.
https://github.com/simonwittber/uniwebserver
Example Component:
https://github.com/simonwittber/uniwebserver
Example Component:
[RequireComponent(typeof(EmbeddedWebServerComponent))] public class FileUpload : MonoBehaviour, IWebResource { public string path = "/upload"; public TextAsset html; EmbeddedWebServerComponent server; void Start () { server = GetComponent<EmbeddedWebServerComponent>(); server.AddResource(path, this); } public void HandleRequest (Request request, Response response) { response.statusCode = 200; response.message = "OK."; response.Write(html.text); } }
Tuesday, January 24, 2017
A widget to list Github repositories.
<div id="github-activity"></div>
<script type="text/javascript">
window.renderGitHubWidget = function(github) {
console.log(github)
var html = '<div class="widget"><ul>';
for (var i=0; i<github.data.length; i++) {
var item = github.data[i];
var url = item.html_url;
if(item.fork) continue;
var repo = '<a href="' + url + '" target="_blank">' + item.name + '</a>';
html += "<li>" + repo + " <br/>" + item.description+ "</li>"
}
html += '</ul></div>';
var el = document.createElement('div');
el.innerHTML = html;
document.getElementById('github-activity').appendChild(el);
};
{
var URL = 'https://api.github.com/users/simonwittber/repos?callback=renderGitHubWidget';
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', URL);
document.head.appendChild(script);
}
</script>
Tuesday, January 03, 2017
Notes on the Unity3D UNET HLAPI
The NetworkManager instantiates a Player prefab. This is your Player Object.
In a two player game, your GameObjects exist conceptually in 3 places, and logically in 2 places. An object exists on each game client, and on the game server. If the game server is also a client, it is called a host, and it shares the GameObject with the client.
By default:
- only methods on components on the Player Object can have the [Command] attribute.
- you can only call [Command] methods from other methods on the Player Object.
It is hard to see which code is server code, and which is client code. I recommend using the [Server] and [Client] attributes liberally to add this information to the source code. When this attribute cannot be applied to a method (only NetworkBehaviours support this attribute) then add the attribute inside a comment.
The NetworkTransform does not provide interpolation when in Transform mode, only when using RigidBody mode. You will need to write this code yourself using [SyncVar].
For fast iterative development, keep the NetworkManager in your development scene, and add the NetworkManagerHUD component. Set this scene as your startup scene, then Build and Run, choose Host or Client from the GUI, then press Play in the editor, and choose Host or Client.
NetworkServer.Spawn only create an instance on the client, and sets it's transform component to match the server. You will have to do any other configuration on this object via a secondary [ClientRpc] call.
In a two player game, your GameObjects exist conceptually in 3 places, and logically in 2 places. An object exists on each game client, and on the game server. If the game server is also a client, it is called a host, and it shares the GameObject with the client.
By default:
- only methods on components on the Player Object can have the [Command] attribute.
- you can only call [Command] methods from other methods on the Player Object.
It is hard to see which code is server code, and which is client code. I recommend using the [Server] and [Client] attributes liberally to add this information to the source code. When this attribute cannot be applied to a method (only NetworkBehaviours support this attribute) then add the attribute inside a comment.
The NetworkTransform does not provide interpolation when in Transform mode, only when using RigidBody mode. You will need to write this code yourself using [SyncVar].
For fast iterative development, keep the NetworkManager in your development scene, and add the NetworkManagerHUD component. Set this scene as your startup scene, then Build and Run, choose Host or Client from the GUI, then press Play in the editor, and choose Host or Client.
NetworkServer.Spawn only create an instance on the client, and sets it's transform component to match the server. You will have to do any other configuration on this object via a secondary [ClientRpc] call.
Less Code is Less Bugs in Less Time
Some favourite quotes from Ron Jeffries, one of the three founders of the Extreme Programming software development methodology...
And this too...
Often you will be building some class and you’ll hear yourself saying “We’re going to need…”.
Resist that impulse, every time. Always implement things when you actually need them, never when you just foresee that you need them.
And this too...
The best way to implement code quickly is to implement less of it. The best way to have fewer bugs is to implement less code.
Is the Unity3D GameObject.GetComponent method slow?
TLDR; No, not really.
Update: Actually, it is slow if you are using IL2CPP. Test results are GetComponent:350, Field:50, Dict:290.
Using the below test script, using GetComponent is about 3x slower than using a direct reference. Caching the return calue in a Dictionary, is slightly faster.
A typical result for me is 232 GetComponent(), 74 for private field and 201 for a dictionary lookup. If you use a builtin Unity type, like Transform, GetComponent is twice as fast.
I made sure the compiler was not optimising out my tests by putting in some fake 'xyzzy' work which is not included in the timing.
Why this simple test? I'm proving to myself it is not terribly bad to use a GetComponent call in an update loop, or keep a Dictionary cache. The call itself is so fast (0.000000232 seconds) that there is really no issue using it a few times inside an update loop.
Update: Actually, it is slow if you are using IL2CPP. Test results are GetComponent:350, Field:50, Dict:290.
Using the below test script, using GetComponent is about 3x slower than using a direct reference. Caching the return calue in a Dictionary, is slightly faster.
A typical result for me is 232 GetComponent(), 74 for private field and 201 for a dictionary lookup. If you use a builtin Unity type, like Transform, GetComponent is twice as fast.
I made sure the compiler was not optimising out my tests by putting in some fake 'xyzzy' work which is not included in the timing.
Why this simple test? I'm proving to myself it is not terribly bad to use a GetComponent call in an update loop, or keep a Dictionary cache. The call itself is so fast (0.000000232 seconds) that there is really no issue using it a few times inside an update loop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetComponentTest : MonoBehaviour {
public int iterations = 1000000;
GetComponentTest testComponentB, testComponentA;
Dictionary<System.Type, Component> cache = new Dictionary<System.Type, Component>();
void Start () {
var sw = new System.Diagnostics.Stopwatch();
for(var i=0; i<iterations; i++) {
sw.Start();
var r = GetComponent<GetComponentTest>();
sw.Stop ();
if(r.name == "xyzzy") {
Debug.Log("xyzzy");
}
}
Debug.Log(sw.ElapsedMilliseconds);
testComponentB = GetComponent<GetComponentTest>();
sw.Reset();
for(var i=0; i<iterations; i++) {
sw.Start();
testComponentA = testComponentB;
sw.Stop ();
if(testComponentA.name == "xyzzy") {
Debug.Log("xyzzy");
}
}
Debug.Log(sw.ElapsedMilliseconds);
sw.Reset();
cache[typeof(GetComponentTest)] = GetComponent<GetComponentTest>();
sw.Reset();
for(var i=0; i<iterations; i++) {
sw.Start();
testComponentA = cache[typeof(GetComponentTest)] as GetComponentTest;
sw.Stop ();
if(testComponentA.name == "xyzzy") {
Debug.Log("xyzzy");
}
}
Debug.Log(sw.ElapsedMilliseconds);
sw.Reset();
}
}
Subscribe to:
Posts (Atom)
Popular Posts
-
These are the robots I've been working on for the last 12 months. They each weigh about 11 tonnes and have a 17 meter reach. The control...
-
This hard-to-see screenshot is a Generic Node Graph Editing framework I'm building. I'm hoping it can be used for any kind of node...
-
So, you've created a car prefab using WheelCollider components, and now you can apply a motorTorque to make the whole thing move along. ...
-
MiddleMan: A Pub/Sub and Request/Response server in Go. This is my first Go project. It is a rewrite of an existing Python server, based o...
-
Why would I ask that question? Python 3 has been available for some time now, yet uptake is slow. There aren't a whole lot of packages i...
-
It is about 8 degrees C this morning. So cold, especially when last week we had high twenties. To help solve the problem, a friend suggeste...
-
After my last post, I decided to benchmark the scaling properties of Stackless, Kamaelia, Fibra using the same hackysack algorithm. Left axi...
-
I'm now using bzr instead of svn. I'm pushing my repositories to: http://exactlysimilar.org/bzr/ I'm also auto publishing docume...
-
Possibly slightly more correct lighting. The rim light is now only applied in the direction of the sun, rather than being purely based on vi...
-
I've just read a newspaper article (courtesy of Kranzky ) from WA Business News documenting the malfeasance, gross negligence and misc...