Record/Play line input positions

There are many situations where you need to record and play exact smae positions of the line. to make sure that behaviour is correct. Or maybe you want even want to make multiplayer drawing and you need to serialize data.

This simple script just demonstrate how you can record data to file and then load it back on scene start

using System.Collections;
using System.IO;
using System.Text;
using PaintCraft.Controllers;
using UnityEngine;
public enum RecorderType
{
Record,
Play
}
public class InputRecorderPlayer : MonoBehaviour
{
private static string FilePath = "Assets/points.log";
public RecorderType Type;
void Start()
{
if (Type == RecorderType.Record && File.Exists(FilePath))
{
File.Delete(FilePath);
}
else
{
StartCoroutine(DoPlay());
}
}
void Update () {
if (Type == RecorderType.Record)
{
DoRecord();
}
}
private int i = 0;
void DoRecord()
{
if (Input.touchCount > 0)
{
StringBuilder sb = new StringBuilder();
sb.Append(i + "|");
foreach (var touch in Input.touches)
{
sb.Append( touch.fingerId + "\t" + touch.position + "|");
}
i++;
sb[sb.Length - 1] = '\n';
File.AppendAllText(FilePath, sb.ToString());
}
}
IEnumerator DoPlay()
{
if (!File.Exists(FilePath))
{
yield break;
}
ScreenCameraController scc = FindObjectOfType<ScreenCameraController>();
yield return null;
yield return null;
yield return null;
StreamReader file = new StreamReader(FilePath);
string line = file.ReadLine();
int i = 0;
do
{
string[] parts = line.Split('|');
line = file.ReadLine();
for (int j = 1; j < parts.Length; j++)
{
ScreenData sd = new ScreenData(parts[j]);
if (string.IsNullOrEmpty(line)) //end line
{
scc.EndLine(sd.FingerId, scc.GetWorldPosition(sd.Position));
}
else if (i == 0) //start line
{
scc.BeginLine(scc.LineConfig, sd.FingerId, scc.GetWorldPosition(sd.Position));
}
else //continue lien
{
scc.ContinueLine(sd.FingerId, scc.GetWorldPosition(sd.Position));
}
}
i++;
yield return null;
yield return null;
} while (!string.IsNullOrEmpty(line));
while ((line = file.ReadLine()) != null)
{
if (string.IsNullOrEmpty(line))
{
break;
}
}
}
struct ScreenData
{
public Vector2 Position;
public int FingerId;
public ScreenData(string data)
{
string[] parts= data.Split('\t');
FingerId = int.Parse(parts[0]);
string[] xy= parts[1].Replace("(", "").Replace(")","").Replace(" ","").Split(',');
Position = new Vector2(float.Parse(xy[0]), float.Parse(xy[1]));
}
}
}

You can see here that I use ScreenCameraController It was just a quick demo so I used this refference to get actual line config and get access to GetWorldPosition method (which is private by default). For production purpose it's better to implement own component inherited from InputController class and use [Begin|End|Continue]Line method. you don't need something else