Search Unity

[Solved] enumerable class.

Discussion in 'Scripting' started by XDSoftworks, May 17, 2017.

  1. XDSoftworks

    XDSoftworks

    Joined:
    Jul 20, 2015
    Posts:
    54
    hi, here's a noob question. i have been wondering how to enumerate custom scripts but cant figure it out. after surfing msdn docs and unity forums and finding nothing related to or very vague on the subject i came here with this novice question!

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. public class Base : MonoBehaviour, IEnumerable{ // Base has a capital so it doesn't register the keyword base
    6.  
    7. blah blah blah blah blah blah
    8. blah blah blah
    9. }
    i get this error with the IEnumerable within the base script:
    error CS0535: `Base' does not implement interface member `System.Collections.IEnumerable.GetEnumerator()'

    and without IEnumerable on the base script i get on my script with the foreach statement :
    error CS1579: foreach statement cannot operate on variables of type `Base' because it does not contain a definition for `GetEnumerator' or is inaccessible.

    the script that im trying to enumerate is public, so it isn't inaccessible. and is crucial to instanced spawning for multiplayer modes.

    im new to this kind of thing and the msdn doc probably slapped it right in my face but i didn't see it as i usually write code later when im tired and there is little distractions, ie (little brothers to bother me)

    any insight into this would be much appreciated. thanks in advance. it might be a while before i can respond if work picks up, i have a very long shift.
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
  3. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    you making the Base class enumerable, but you didn't specify how you want it to enumerate. when you call foreach on the base class, what exactly is it going to iterate. and in what order?

    you need to define such things for the compiler. we can't really help you here either as you haven't told us how you want it to enumerate either.
     
  4. XDSoftworks

    XDSoftworks

    Joined:
    Jul 20, 2015
    Posts:
    54
    i need to iterate through a list of spawn objects then return whether it is a world default spawn, checkpoint, player placed spawn or base spawn. the spawn controller script gets all the objects with a spawn tag or a determined spawn component then assigns them to the spawns list, it then returns their spawn components and assigns them to the components list, then the Base script checks the "base or spawn for child objects that have the spawn point component counting each sub spawn to determine if it is a point spawn (includes world spawn, checkpoints, and player placed spawns), small base, medium base or a large base. all spawn points are listed in the base spawn list which the spawn controller can look at at anytime, it mostly works for singleplayer as nothing has to be accessed from another class. when i tried to instance it for multiplayer it didn't work. im gonna make a little animation to explain this it will be far easier than by text. i will use my plain and very simple desert test map as everything stands out against the backdrop
     
  5. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,529
    When you write something like `class Foo : Something, IAnything` you're telling it that the class Foo uses the interface IAnything. Interfaces are basically contracts. The compiler will see that `hey, this class Foo uses the interface called IAnything, so I better make sure that Foo actually contains the methods and variables that the Interface requires it to have.`

    If IAnything requires that you implement 'void MyInterfaceMethod()' then the compiler absolutely requires anything that implements that interface to also have a `void MyInterfaceMethod()` or else it will absolutely refuse to compile.

    So the errors you're seeing are exactly that. You've basically said that your class guarantees the IEnumerable interface components, but you didn't bother to actually put them in your class so the compiler is saying `hey silly, you can't do that. You have to make this class fulfill the contract that this interface guarantees will exist.`\

    I wrote a small blog post on interfaces.
     
    Kiwasi and XDSoftworks like this.
  6. XDSoftworks

    XDSoftworks

    Joined:
    Jul 20, 2015
    Posts:
    54
    wow... if i only would have known that earlier :D im like a cave man when it comes to interfaces like that, im gonna have to rewrite alot of my code as there may be a bunch of performance pit falls in it due to using other methods not using anything like that... what i currently have to do stuff like what you have on your blog i use stuff like this:
    Code (CSharp):
    1. if (useraycast){
    2. foreach(Collider col in Physics.OverlapSphere(transform.position, radius))
    3. {
    4. if (col.GetComponent<Rigidbody>() != null){
    5. col.GetComponent<Rigidbody>().AddExplosionForce(force,transform.position,radius,upwardsModifier,forceMode);
    6. }else if (col.GetComponent<Rigidbody>() == null){
    7. Transform t = col.transform;
    8. while (t.parent != null)
    9. {
    10. if (t.parent.GetComponent<Rigidbody>() != null){
    11.  
    12. RaycastHit hit;
    13. if(Physics.Raycast(transform.position,col.transform.position-transform.position,out hit,radius))
    14. {
    15. if(hit.collider == col)
    16. {
    17. t.parent.GetComponent<Rigidbody>().AddExplosionForce(force,transform.position,radius,upwardsModifier,forceMode);
    18. }
    19. }
    20. }
    21. t = t.parent.transform;
    22. }
    23. }
    24. }
    25. foreach(Collider col in Physics.OverlapSphere(transform.position, radius))
    26. {
    27. if(col.transform.root.GetComponent<physicscont>() != null)
    28. {
    29. RaycastHit hit;
    30. if(Physics.Raycast(transform.position,col.transform.position-transform.position,out hit,radius))
    31. {
    32. if(hit.collider == col)
    33. {
    34. if(col.transform.root.gameObject.GetComponent<physicscont>() != null)
    35. {
    36. physicscont phy = col.transform.root.gameObject.GetComponent<physicscont>();
    37. //phy.ragdoll = true;
    38. //phy.ragtime = 3;
    39. float effect = 1 - (Vector3.Distance(transform.position, phy.gameObject.transform.position)) / radius;
    40. if (superbomb){
    41. phy.arm.inputdamage = force * effect * 0.4f;
    42. }else {phy.arm.inputdamage = force * effect * 0.5f; }
    43. phy.type = this.gameObject.name;
    44. if (!String.IsNullOrEmpty(shotby)){
    45. phy.shotby = shotby;
    46. }
    47. }
    48. }
    49. }
    50. }
    51. }
    52. foreach(Collider col in Physics.OverlapSphere(transform.position, radius))
    53. {
    54. if(col.transform.root.GetComponent<npc>() != null)
    55. {
    56. RaycastHit hit;
    57. if(Physics.Raycast(transform.position,col.transform.position-transform.position,out hit,radius))
    58. {
    59. if(hit.collider == col)
    60. {
    61.     if(col.transform.root.gameObject.GetComponent<npc>() != null)
    62. {
    63. npc np = col.transform.root.gameObject.GetComponent<npc>();
    64. float effect = 1 - (Vector3.Distance(this.transform.position, np.gameObject.transform.position)) / radius;
    65. if (superbomb){
    66. np.health -= force * effect * 0.2f;
    67. }else {np.health -= force * effect * 0.17f; }
    68. np.type = this.gameObject.name;
    69. np.hitby = type;
    70. if (!String.IsNullOrEmpty(shotby)){
    71. np.shotby = shotby;
    72. }
    73. }
    74. }
    75. }
    76. }
    77. }
    78. foreach(Collider col in Physics.OverlapSphere(transform.position, radius))
    79. {
    80. if(col.transform.GetComponent<Rigidbody>() != null)
    81. {
    82. RaycastHit hit;
    83. if(Physics.Raycast(transform.position,col.transform.position-transform.position,out hit,radius))
    84. {
    85. if(hit.collider == col && hit.transform.tag == "building panel")
    86. {
    87. Rigidbody rb = col.GetComponent<Rigidbody>();
    88. rb.isKinematic = false;
    89. rb.transform.parent = null;
    90. rb.AddExplosionForce(force * 0.05f,transform.position,radius,upwardsModifier,ForceMode.VelocityChange);
    91. }
    92. }
    93. }
    94. }
    95. foreach(Collider col in Physics.OverlapSphere(transform.position, radius))
    96. {
    97. if(col.transform.GetComponent<wingcontroller>() != null)
    98. {
    99. RaycastHit hit;
    100. if(Physics.Raycast(transform.position,col.transform.position-transform.position,out hit,radius))
    101. {
    102. if(hit.collider == col)
    103. {
    104. wingcontroller wc = col.transform.root.GetComponent<wingcontroller>();
    105. float effect = 1 - (Vector3.Distance(this.transform.position, wc.gameObject.transform.position)) / radius;
    106. if (superbomb){
    107. wc.shield -= force * effect * 0.2f * wc.armour;
    108. }else {wc.shield -= force * effect * 0.17f * wc.armour; }
    109. }
    110. }
    111. }
    112. }
    113. }
    not everything uses the above or similar but it has to change as it is somewhat slow, if you do insane stuff like blow up 400 bombs on the same frame (due to the fast paced gameplay and the amount of players to be in game on multiplayer it might be a reality). thanks for the resource, its the clearest one i have seen yet and im gonna have to read it a couple times to try and wrap my head around it while attempting to implement it as i have never used anything like it before.
     
  7. XDSoftworks

    XDSoftworks

    Joined:
    Jul 20, 2015
    Posts:
    54
    i figured it out thanks, that was the best tutorial yet.
     
    LaneFox likes this.
  8. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,529
    Glad it helped! :)
     
  9. XDSoftworks

    XDSoftworks

    Joined:
    Jul 20, 2015
    Posts:
    54
    hi, i have one more question. i was wondering how to make interface variables appear in the inspector, i have been reading how to do it but most say unity doesn't like it and always "forgets" each instance. also i can't seem to get it to communicate with objects using the interface, it has no errors but i cant change things like health.
     
  10. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,529
    Variables are exposed as things derived from Objects, so there is no 'easy' way to make an Interface exposed as a field in the inspector.

    There's a few ways to do it, but it requires some backer fields, custom inspectors or other hackery.
     
  11. XDSoftworks

    XDSoftworks

    Joined:
    Jul 20, 2015
    Posts:
    54
    hi, i have found why i couldn't communicate between objects with the interface and no longer need to expose the variables, i feel like a moron for not seeing it. i had the void methods implemented but no functions in them. i seem to have a really bad habit of doing that :D