How to not serialize List.subList

A quite undocumented Java quirk struck me last week regarding the serialization of java.util.List objects. The lists are normally serializable and just dump their object content nicely into the output. Little is it known that List.subList() does not produce a list of the same type as the original, but instead a RandomAccessSubList. In the documentation, this list is simply called a ”view”.

In shorter words, here is a serialization (XStream) and output of an ArrayList containing some integers:

List<Integer> list = new ArrayList<Integer>();
list.add(1); list.add(2); list.add(3);
System.out.println(serializer.toXML(list));
<list id="1">
  <int>1</int>
  <int>2</int>
  <int>3</int>
</list>

Here is the same procedure but using a sublist:

list = list.subList(0, 3);
<java.util.RandomAccessSubList id="1">
  <l class="list" id="2">
    <int>1</int>
    <int>2</int>
    <int>3</int>
  </l>
  <offset>0</offset>
  <size>3</size>
  <expectedModCount>3</expectedModCount>
</java.util.RandomAccessSubList>

This view-wrapped list plays nicely and is not noticable in most cases. However, if you save this serialization for later use, the mod count will get saved with it. Tampering the unmarshalled list at a later time will produce a rather surprising ConcurrentModificationException.

The moral of this story is to always wrap calls to List.subList() in another container, which implicitly calls addAll().

End transmission.

Jazz piece for wurlitzer and guitar

Jazz piece in 4/4 and 3/4 measures driven by guitar and wurlitzer.

217 by CunningCode

Quirks with java.util.zip

A few notes on the peculiars of java.util.zip

  • Root ZipEntry cannot begin with /
  • Empty directories needs an entry before children
  • Does not accept backslashes as separators in entries, i.e on Windows do not use file path.
  • Directory entries must end with /
Below, a recursive hack to zip a directory from its root. The base is substringed off of the ZipEntry and backslash path separators are replaced. Empty directories are included in the zip.

	private static final void zip(File directory, File zipFile, File base, ZipOutputStream zos) throws IOException {

		File[] files = directory.listFiles();
		byte[] buffer = new byte[8192];
		int read = 0;

		if(null == base) base = directory;

		for (int i = 0, n = files.length; i < n; i++) {
			if (files[i].isDirectory()) {
				String path = files[i].getPath().substring(base.getPath().length() + 1);
				path = path.replaceAll("\\\\", "/");
				ZipEntry entry = new ZipEntry(path+"/");
				zos.putNextEntry(entry);
				zip(files[i], zipFile, base, zos);
			} else {
				FileInputStream in = new FileInputStream(files[i]);
				String path = files[i].getPath().substring(base.getPath().length() + 1);
				path = path.replaceAll("\\\\", "/");
				ZipEntry entry = new ZipEntry(path);
				zos.putNextEntry(entry);
				while (-1 != (read = in.read(buffer))) {
					zos.write(buffer, 0, read);
				}
				in.close();
			}
		}
	}

Rag hank invasion

A composited painting for background art.

Background artwork sketch

Background artwork sketch with some spotlighted lightmaps. Hank rides a bear cub!

Timed animation groups

With the release of Unity 3.4 there were some news on the animation culling methods – it can now be selected as clip bounds, renderer bounds or user specified bounds. A leap much needed. However, things get tricky when you need to coordinate several animated objects, for instance elevator platforms that move in a synchronized manner.

The most obvious solution is to set the Animation component to Always Animate. It is also a bad solution for mobile devices since you get a lot of offscreen interpolation action. The next thing that comes to mind is to align the user-specified boxes. That’s very awkward and doesn’t produce an exact synch, and if you move one of the animated objects slightly you’ll have to redo the bounds.

I present a small script to enable the Animation components on all child objects. Slap this on an empty game object with your animated game objects inside of it, and add a trigger to it.

using UnityEngine;
using System.Collections;

public class EnableAnimationOnTrigger : MonoBehaviour {

	// Use this for initialization
	void Start () {
		SetAnimation(false);
	}

	void SetAnimation(bool enabled) {
		foreach(Transform tr in GetComponentsInChildren<Transform>()) {
			Animation a = tr.GetComponent<Animation>();
			if(null != a) {
				a.enabled = enabled;
			}
		}
	}

	void OnTriggerEnter(Collider other) {
		foreach(Transform tr in other.gameObject.GetComponentsInChildren<Transform>()) {
			if(tr.CompareTag("Player")) {
				SetAnimation(true);
				break;
			}
		}
	}

	void OnTriggerExit(Collider other) {
		foreach(Transform tr in other.gameObject.GetComponentsInChildren<Transform>()) {
			if(tr.CompareTag("Player")) {
				SetAnimation(false);
				break;
			}
		}
	}
}

The reason for looping the colliding object’s transforms is that the player might be temporarily parented to an object that moves into the trigger zone (e.g. trolly, elevator). If there is a possibility of the player dying or otherwise being removed from the zone without passing the trigger bounds for an exit, you will naturally have to call SetAnimation(false) on those occasions.

Bai.

 

Hierarchical empty game object

This is a simple editor extension for Unity3D which adds a GameObject menu entry to insert an empty game object in the hierarchy. The default, and very cumbersome, functionality is that the game object gets inserted into the scene root. You then have to drag the object across your entire hierarchy to drop it in its place. This is inserts an empty object at the currently selected transform.

using UnityEngine;
using UnityEditor;
public class InsertChild : MonoBehaviour {
  [MenuItem("GameObject/Insert Child)]
  static void InsertChild() {
    GameObject go = new GameObject("Insert GameObject");
    if(Selection.activeTransform != null)
      go.transform.parent = Selection.activeTransform;
  }
}

Note that the script needs to live in the Assets/Editor folder for the editor to notice it.

Animated local scale and IOS performance

This is a scribble that hopefully can save some Unity developers the trouble on redoing their animation structure late in the project. Using a programmatic approach (coroutines) to animate an object’s scale is quite common, especially in the GUI section. A new coin, one up, life lost – you animate the gui icon scale to grab attention. Big whoop.

Little is it known that programmatic scale animations are big performance hogs on the mobile devices, or at least IOS. Probably on more powerful devices as well, but it’s hard to notice unless you profile extensively or if you’re completely out of render time. Why is it like this? No one knows yet, apparently. My unfounded guess is that a change in scale for an object that was previously dynamically batched jabs the batching system, which leads to some cumbersome calculation or garbage collect behind the scenes.

My finding (and others too) is that for a localScale animation to run smooth, you either have to use an animation clip (Unity’s generic animation tool) or use bone based animations exported from your modelling application. The fact that animation clips do not produce any noticable lag should probably void the previous guess about impact on batching, come to think of it.

TLDR:

  • OK to animate localScale with AnimationClip
  • OK to animate localScale with bones.
  • NOT OK to animate localScale programmatically (coroutines, Update(), etc).

 

Breakout, Arkanoid collisions in Unity

When working on Arkanoid / Breakout style gameplay you can’t reliably use PhysX, or any reasonably fast physics solver for that matter, to handle collisions. Instead of relying on small timesteps, a common method is to perform a short raycast when moving the ball to its next position. You intercept any edges and reflect the velocity / direction around the normal.  It’s pretty ubiquitous code if you ever worked in something that isn’t backed by physics, but perhaps it can save someone the grief of trying high velocity brick-bouncing gameplay with rigidbody physics. Pseudo code below.

void Update() {

  Vector3 velocityComponent = velocity * Time.deltaTime;
  Vector3 newPosition = transform.position + velocityComponent;
  float rayLength = velocityComponent.magnitude;
  RaycastHit hit;

  if(Physics.Raycast(transform.position, velocityComponent, hit, rayLength)) {
     GameObject go = hit.transform.gameObject;
     if(!go.CompareTag("MyBallIgnoreTag")) {
       velocity = Vector3.Reflect(velocity, hit.normal);
       NotifyObject(go, hit);
     }
  } else {
    position = newPosition;
  }
}

Numerous cycle saving tricks can be added to avoid casting each frame, depending on your scene. Raycast layering, adaptive ray length, etc. It doesn’t necessarily interfere with normal physics calculations, and won’t suffer from high velocity artifacts or double-edged collisions. In our game, this code is used for ball/brick collisions, where a normal rigid body collision solver can produce very weird collision normals on sharp edges.

Precomputed Catmull-Rom Spline Implementation

Here’s a simple cached C Sharp CR spline that takes control point input from a series of Transforms. Since GameObject.GetComponentsInChildren doesn’t supply an ordered iterator, the control points has to be assigned in the Inspector. It’s based on this spline code, so check that out as well.

The assigned transforms are rendered as spheres if you enable Gizmo draw mode. The actual curve render can also be toggled from the Inspector. Source code below.

using UnityEngine;
using System.Collections;

[System.Serializable]
public class CRSpline : MonoBehaviour {

 // User input ctrl points
 public Transform[] orderedPoints;

 // Renders the spline in game view
 public bool renderInGameView = true;

 // Renders the control points in gizmo draw mode
 public bool renderGizmos = true;

 // Same ctrl points, but padded endpoints
 private Transform[] pts; 

 // Number of subdivisions
 private int numSections = 60;

 // Precomputed cache
 private float[] cacheIx;
 private Vector3[] cacheVal;

 void Awake() {
   BuildCache(40);       
 }

 public void Update() {

   if(!renderInGameView) return;

   Vector3 lastPoint = InterpCached(0f);

   for(int i=0; i<numSections; i++) {
     float p = i / (float)numSections;
     Vector3 point = InterpCached(p);
     Debug.DrawLine(lastPoint, point, Color.white);       
     lastPoint = point;
   }   
 }

 // Draw spheres at the control points in edit mode / gizmo draw
 public void OnDrawGizmos() {

   if(!renderGizmos) return;

   if(pts != null) {
     foreach(Transform t in orderedPoints) {
       Gizmos.DrawSphere(t.position, 0.05f);               
     }   
   }
 }

 // Computes a cached version of the spline
 private void BuildCache(int numSegments) {

   // Pad control points in each end to clamp curve
   pts = new Transform[orderedPoints.Length + 2];

   for(int i=0; i<orderedPoints.Length; i++) {
     pts[i+1] = orderedPoints[i];
   }  

   pts[0] = pts[1];
   pts[pts.Length - 1] = pts[pts.Length - 2];

   // Build a cache table
   cacheVal = new Vector3[numSegments];
   cacheIx = new float[numSegments];
   for(int i=0; i<numSegments; i++) {
     float t = i / (float)numSegments;   
     Vector3 val = Interp(t);
     cacheIx[i] = t;
     cacheVal[i] = val;
   }
 }

 // Does a LERP on the precomputed cache, built at Awake.
 public Vector3 InterpCached(float t) {
   for(int i=0; i<cacheIx.Length-1; i++) {
     if(t >= cacheIx[i] && t < cacheIx[i+1])  {
       float rv = cacheIx[i+1] - cacheIx[i];
       float tv = t - cacheIx[i];
       return Vector3.Lerp(cacheVal[i], cacheVal[i+1], tv / rv);
     }
   }
   return cacheVal[cacheVal.Length-1];
 }

 /** Calculates the CR spline at T [0,1] */
 public Vector3 Interp(float t) {
   int numSections = pts.Length - 3;
   int currPt = Mathf.Min(Mathf.FloorToInt(t * (float) numSections), numSections - 1);
   float u = t * (float) numSections - (float) currPt;

   Vector3 a = pts[currPt].position;
   Vector3 b = pts[currPt + 1].position;
   Vector3 c = pts[currPt + 2].position;
   Vector3 d = pts[currPt + 3].position;

   return .5f * (
   (-a + 3f * b - 3f * c + d) * (u * u * u)
   + (2f * a - 5f * b + 4f * c - d) * (u * u)
   + (-a + c) * u
   + 2f * b
   );
 }
}

So, you would use the CRSpline.InterpCached(float) for efficient use of the spline during gameplay. If you need actual values and not interpolated ones, CRSpline.Interp(float) can be used.