Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
1
Question by EpicX112 · Jul 24, 2016 at 06:22 AM · c#dictionaryhashtablehash

Dictionary doesn't find value when using new object as key

I am trying to build a Dictionary of PathNodes keyed by NodeCoordinates. I have overridden GetHashCode in NodeCoordinate and it should return a constant unique value. If I loop through the keys of the dictionary, the lookup works fine, but if I create a new NodeCoordinate with the coordinates of a PathNode that should exist, the lookup fails even though the hash codes are equal.

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class PathNode : MonoBehaviour {
 
     public static Dictionary<NodeCoordinate, PathNode> pathNodes;
 
     public PathNode left;
     public PathNode right;
     public PathNode forward;
     public PathNode backward;
 
     private NodeCoordinate coord;
 
     void Awake()
     {
         if (PathNode.pathNodes == null)
         {
             PathNode.pathNodes = new Dictionary<NodeCoordinate, PathNode>();
         }
 
         NodeCoordinate coord = new NodeCoordinate(transform.position.x, transform.position.z);
         this.coord = coord;
         PathNode.pathNodes.Add(coord, this);
 
         NodeCoordinate leftChord = new NodeCoordinate(coord.x - 1, coord.z);
         NodeCoordinate rightChord = new NodeCoordinate(coord.x + 1, coord.z);
         NodeCoordinate forwardChord = new NodeCoordinate(coord.x, coord.z + 1);
         NodeCoordinate backwardChord = new NodeCoordinate(coord.x, coord.z - 1);
 
         if (PathNode.pathNodes.ContainsKey(leftChord))
         {
             this.left = PathNode.pathNodes[leftChord];
             this.left.right = this;
         }
         if (PathNode.pathNodes.ContainsKey(rightChord))
         {
             this.right = PathNode.pathNodes[rightChord];
             this.right.left = this;
         }
         if (PathNode.pathNodes.ContainsKey(forwardChord))
         {
             this.forward = PathNode.pathNodes[forwardChord];
             this.forward.backward = this;
         }
         if (PathNode.pathNodes.ContainsKey(backwardChord))
         {
             this.backward = PathNode.pathNodes[backwardChord];
             this.backward.forward = this;
         }
     }
 
     private static bool debug = true;
 
     void Update()
     {
         if (debug)
         {
             foreach (NodeCoordinate coord in PathNode.pathNodes.Keys)
             {
                 Debug.Log(coord + " : " + PathNode.pathNodes[coord] + " : " + coord.GetHashCode());
             }
 
             foreach (PathNode node in PathNode.pathNodes.Values)
             {
                 NodeCoordinate leftChord = new NodeCoordinate(node.coord.x - 1, node.coord.z);
                 PathNode leftNode;
                 Debug.Log("Left: " + leftChord + " : " + PathNode.pathNodes.TryGetValue(leftChord, out leftNode) + " : " + leftChord.GetHashCode());
             }
 
             debug = false;
         }
     }
 }
 
 public class NodeCoordinate
 {
     public float x;
     public float z;
 
     public NodeCoordinate(float x, float z)
     {
         this.x = x;
         this.z = z;
     }
 
     public bool Equals(NodeCoordinate coord)
     {
         return (this.x == coord.x && this.z == coord.z);
     }
 
     public override int GetHashCode()
     {
         return string.Format("{0}x{1}", this.x, this.z).GetHashCode();
     }
 
     public override string ToString()
     {
         return "Coordinate: " + this.x + " x " + this.z;
     }
 }

This is the output from my little debug:

alt text

As you can see, when looping through the keys, the lookups with hashcodes 2137067561 and 1824497336 work, but when I instantiate a new NodeCoordinate and try to look it up, it has the same hashcode but the lookup fails.

debug.png (45.2 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Jul 24, 2016 at 03:28 PM

It's total overkill to use a class for this. Use a struct. If two structs are compared the compiler automatically compares it's content. I'm also wondering why you actually create a seperate class / struct for this. Why don't you simply use Vector2?

Keep in mind that comparing float values can lead to all sorts of problems

If you want to use integer values instead of floats you would have to create your own struct. I once created my Vector3i struct for that very same purpose.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Jul 24, 2016 at 03:31 PM 0
Share

ps: In your original code you did not override the Equals method, you hide it.

avatar image EpicX112 · Jul 24, 2016 at 03:42 PM 0
Share

That makes a lot of sense to use Vector2, I will do that, thank you.

avatar image
0

Answer by EpicX112 · Jul 24, 2016 at 03:01 PM

So for some reason, when I add a IEqualityComparer with the exact same logic, it works.

Changed the declaration of the dictionary to this:

 if (PathNode.pathNodes == null)
         {
             PathNode.pathNodes = new Dictionary<NodeCoordinate, PathNode>(new NodeCoordinateComparer());
         }

And added this:

 public class NodeCoordinateComparer : IEqualityComparer<NodeCoordinate>
 {
     public bool Equals(NodeCoordinate a, NodeCoordinate b)
     {
         return (a.x == b.x && a.z == b.z);
     }
 
     public int GetHashCode(NodeCoordinate coord)
     {
         return string.Format("{0}x{1}", coord.x, coord.z).GetHashCode();
     }
 
 
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

dictionary of functions? 1 Answer

Is it possible to shuffle a Dictionary? Any other shuffleable data structure we can access both by key and index? 2 Answers

Traffic Light State Machine Dictionary Issues 2 Answers

Getting "object reference not set" error when creating a list dictionary. 1 Answer

Null reference on dictionary with Unity's Text Localisation tutorial 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges