- Home /
Using C# dynamic typing with Unity 4.3.4f1
I have written generic GUi framework in C# that uses dependency injection to run on almost any platform.
I am trying t port it to Unity3D right now but I have run into issues. I have a nice, clean generic vector class that uses dynamic to implement the overloaded operators. Unity complained about the implicit type coercion first, so i fixed that and made it explicit. I also changed the .NEt version from 2.0 Subset to 2.0 in client perferences.
Now it compiles but I get the following error from the Internals:
Internal compiler error. See the console log for more information. output was:error CS0518: The predefined type System.Runtime.CompilerServices.CallSite' is not defined or imported error CS0518: The predefined type
System.Runtime.CompilerServices.CallSite`1' is not defined or imported error CS0518: The predefined type System.Runtime.CompilerServices.CallSite' is not defined or imported error CS0518: The predefined type
System.Runtime.CompilerServices.CallSite`1' is not defined or imported error CS0518: The predefined type `System.Runtime.CompilerServices.CallSite' is not defined or imported
Id appreciate any thoughts on how to make this work.
Here's an example of the code:
public struct Vector2<T> where T: struct {
public Vector2(T x, T y):this(){
X = x;
Y = y;
}
public T X {
get ;
set ;
}
public T Y {
get ;
set ;
}
public static Vector2<T> operator +(Vector2<T> lhs, Vector2<T> rhs)
{
return new Vector2<T>((T)((dynamic)lhs.X+rhs.X),(T)((dynamic)lhs.Y+rhs.Y));
}
(etc ... )
Answer by makeshiftwings · Apr 14, 2014 at 12:50 AM
You're not allowed to use the "dynamic" keyword at all; Unity uses a very old version of Mono that won't compile any of the newer syntax that was introduced in .NET 4.
To get around it, I'd suggest casting to a double, doing the addition, then casting back to T. That should be safe for all built-in numeric types at least.
Thanks yeah, that ugly ass hack is exactly what I came to myself.
I dislike it because its sort of lying. You can make a Vector2 and think you are working with ints, but be subject to round off error on the high end. But i guess its the best Unity can do for now.
I'll post my changed code for anyone else struggling with this.
Unity really aught to find a way to march more in step with the mono builds...
Answer by Jeff-Kesselman · Apr 14, 2014 at 01:02 AM
So, as suggested, this was my answer. Its nasty on a couple of levels but it will work...
using System;
/// <summary>
/// This class imp[lements various useful math functions
/// </summary>
namespace WWUtils.Math
{
/// <summary>
/// This is a hack that treats all numbers as doubles. Its temporary because
/// Unity does not support dynamic properly
/// </summary>
public struct Vector2<T> where T: struct {
internal double x;
internal double y;
public Vector2(T x, T y):this(){
X = x;
Y = y;
}
private static T ConvertFrom(double v){
return (T)(object)v;
}
private static double ConvertTo(T v){
return (double)(object)v;
}
public T X {
get {return ConvertFrom(x);}
set {x=ConvertTo(value);}
}
public T Y {
get {return ConvertFrom(y);}
set {y=ConvertTo(value);}
}
public static Vector2<T> operator +(Vector2<T> lhs, Vector2<T> rhs)
{
return new Vector2<T>(ConvertFrom(lhs.x+rhs.x),
ConvertFrom(lhs.y+rhs.y));
}
public static Vector2<T> operator -(Vector2<T> lhs, Vector2<T> rhs)
{
return new Vector2<T>(ConvertFrom(lhs.x-rhs.x),
ConvertFrom(lhs.y-rhs.y));
}
public static Vector2<T> operator *(Vector2<T> lhs, T scaler)
{
return new Vector2<T>(ConvertFrom(lhs.x*ConvertTo(scaler)),
ConvertFrom(lhs.y*ConvertTo(scaler)));
}
public static Vector2<T> operator /(Vector2<T> lhs, T scaler)
{
return new Vector2<T>(ConvertFrom(lhs.x/ConvertTo(scaler)),
ConvertFrom(lhs.y/ConvertTo(scaler)));
}
/// <summary>>
/// Dot product
/// </summary>
/// <param name="lhs">Lhs.</param>
/// <param name="rhs">Rhs.</param>
public T Dot(Vector2<T> rhs){
return ConvertFrom((x * rhs.x) + (y * rhs.y));
}
public Vector2<T> Rotate(float deg){
float rad = (float)(deg * System.Math.PI / 180);
float s = (float)System.Math.Sin(rad);
float c = (float)System.Math.Cos(rad);
return new Vector2<T>(ConvertFrom((x * c) - (y * s)),
ConvertFrom((x * s) + (y * c)));
}
public override string ToString ()
{
return string.Format ("[Vector2("+X+","+Y+")]");
}
public static implicit operator Vector2<T>(Vector3<T> someValue)
{
return new Vector2<T>(someValue.X,someValue.Y);
}
}
public struct Vector3<T> where T: struct {
double x;
double y;
double z;
public Vector3(T x, T y, T z):this(){
X = x;
Y = y;
Z = z;
}
private static T ConvertFrom(double v){
return (T)(object)v;
}
private static double ConvertTo(T v){
return (double)(object)v;
}
public T X {
get {return ConvertFrom(x);}
set {x=ConvertTo(value);}
}
public T Y {
get {return ConvertFrom(y);}
set {y=ConvertTo(value);}
}
public T Z {
get {return ConvertFrom(z);}
set {z=ConvertTo(value);}
}
public static Vector3<T> operator +(Vector3<T> lhs, Vector3<T> rhs)
{
return new Vector3<T>(ConvertFrom(lhs.x+rhs.x),
ConvertFrom(lhs.y+rhs.y),
ConvertFrom(lhs.z+rhs.z));
}
public static Vector3<T> operator -(Vector3<T> lhs, Vector3<T> rhs)
{
return new Vector3<T>(ConvertFrom(lhs.x-rhs.x),
ConvertFrom(lhs.y-rhs.y),
ConvertFrom(lhs.z-rhs.z));
}
public static Vector3<T> operator *(Vector3<T> lhs, T scaler)
{
return new Vector3<T>(ConvertFrom(lhs.x*ConvertTo(scaler)),
ConvertFrom(lhs.y*ConvertTo(scaler)),
ConvertFrom(lhs.z*ConvertTo(scaler)));
}
public static Vector3<T> operator /(Vector3<T> lhs, T scaler)
{
return new Vector3<T>(ConvertFrom(lhs.x/ConvertTo(scaler)),
ConvertFrom(lhs.y/ConvertTo(scaler)),
ConvertFrom(lhs.z/ConvertTo(scaler)));
}
///<summary>
/// The cross product
/// cx = aybz - azby
/// cy = azbx - axbz
/// cz = axby - aybx
/// </summary>
/// <param name="lhs">Lhs.</param>
/// <param name="rhs">Rhs.</param>
public static Vector3<T> operator *(Vector3<T> lhs, Vector3<T> rhs)
{
T cx = ConvertFrom((lhs.y * rhs.z) - (lhs.z * rhs.y));
T cy = ConvertFrom((lhs.z * rhs.x) - (lhs.x * rhs.z));
T cz = ConvertFrom((lhs.x * rhs.y) - (lhs.y * rhs.x));
return new Vector3<T> (cx, cy, cz);
}
/// <summary>>
/// Dot product
/// </summary>
/// <param name="lhs">Lhs.</param>
/// <param name="rhs">Rhs.</param>
public T Dot(Vector3<T> rhs){
return ConvertFrom((x * rhs.x) + (y * rhs.y)+ (z * rhs.z));
}
public override string ToString ()
{
return string.Format ("[Vector3("+X+","+Y+","+Z+")]");
}
public static implicit operator Vector3<T>(Vector2<T> someValue)
{
return new Vector3<T>(someValue.X,someValue.Y,default(T));
}
}
Your answer
