I am needing to do a lookup on a large bool set using x,y,z coordinates(integers only). I am trying to determine if a block is traversable at x,y,z location.
Currently I am using an array bool[,,]. However, this is not very flexible, and the size quickly gets massive for a decent sized map.
I thought a dictionary that only holds the true values would be much more flexible and less memory hungry. I created a struct Vector3Int to hold the x,y,z values and use as a dictionary key. Dictionary looks like Dictionary<Vector3Int, bool>.
However, doing Dictionary lookups with this key appears to be 20-100 times slower than the array lookups with x,y,z integers.
Is there a faster/better way to do this? I am using the lookups for pathfinding, so the lookup needs to be quite fast as there may be hundreds/thousands of lookups for a single path.
Vector3Int code:
public struct Vector3Int
{
public int x,y,z;
public Vector3Int(int x, int y, int z)
{
    this.x =x;
    this.y=y;
    this.z=z;
}
//checks for equality
public static bool operator ==(Vector3Int a, Vector3Int b)
{
    return a.x==b.x && a.y ==b.y && a.z ==b.z;
}
public override bool Equals(object obj)
{
    return obj is Vector3Int && this == (Vector3Int)obj;
}
public override int GetHashCode ()
{
    return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode();
}
//checks the two vectors for non-equality
public static bool operator !=(Vector3Int a, Vector3Int b)
{
    return !(a==b);
}
}
Array lookup:
bool[,,] worldWalkable= new bool[1000,1000,1000];
public bool CheckWalkable(int x, int y, int z)
{
    return worldWalkable[x,y,z];
}
Vs Dictionary Lookup:
Dictionary<Vector3Int, bool> worldTraversable = new Dictionary<Vector3Int, bool>();
public bool CheckTraversable(Vector3Int block)
{
    bool tempBool;
    worldTraversable.TryGetValue(block, tempBool);
    return tempBool;
} 
Test code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SpeedTest : MonoBehaviour {
Dictionary<Vector3Int, bool> testDict;
bool[,,] testArray;
// Use this for initialization
void Start () 
{
    InitializeContainers();
    RunTest();
}
void InitializeContainers()
{
    testDict= new Dictionary<Vector3Int, bool>(1000);
    for(int i=0; i<10; i++)
    {
        for(int j=0; j<10; j++)
        {
            for(int k=0; k<10; k++)
            {
                testDict[new Vector3Int(i,j,k)]=true;
            }
        }
    }
    testArray=new bool[10,10,10];
}
void RunTest()
{
    bool tempBool;
    float timer1, timer2;
    timer1=Time.realtimeSinceStartup;
    for(int i=0; i<10; i++)
    {
        for(int j=0; j<10; j++)
        {
            for(int k=0; k<10; k++)
            {
                tempBool= testDict[new Vector3Int(i,j,k)];
            }
        }
    }
    timer2=Time.realtimeSinceStartup;
    Debug.Log("Dictionary completion time: "+(timer2-timer1)*1000+"ms");
    timer1=Time.realtimeSinceStartup;
    for(int i=0; i<10; i++)
    {
        for(int j=0; j<10; j++)
        {
            for(int k=0; k<10; k++)
            {
                tempBool=testArray[i,j,k];
            }
        }
    }
    timer2=Time.realtimeSinceStartup;
    Debug.Log("Array completion time: "+(timer2-timer1)*1000+"ms");
}
}
Edit: Revised struct that fixes the problem:
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
//makes a Vector3 of integers
public struct Vector3Int : IEquatable<Vector3Int>
{
public int x,y,z;
public Vector3Int(int x, int y, int z)
{
    this.x =x;
    this.y=y;
    this.z=z;
}
public bool Equals(Vector3Int other)
{
    return other.x==this.x && other.y==this.y && other.z==this.z;
}
public static bool operator ==(Vector3Int a, Vector3Int b)
{
    return a.Equals(b);
}
public override bool Equals(object obj)
{
    if(obj==null || !(obj is Vector3Int))
        return false;
    return Equals((Vector3Int)obj);
}
public override int GetHashCode ()
{
    return x ^ (y<<10) ^ (z<<10);
}
public override string ToString ()
{
    return string.Format ("("+x+", "+y+", "+z+")");
}
public static bool operator !=(Vector3Int a, Vector3Int b)
{
    return !(a==b);
}
}
The issue was boxing/unboxing like Alexei suggested. Used the directions from this link to fix the issue.
 
     
     
     
     
    