Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Assets\Scripts\Player system\PlayerOxygen.cs(10,33): error CS0236: A field initializer cannot refere

Discussion in 'Scripting' started by Jekirutu, Feb 22, 2022.

  1. Jekirutu

    Jekirutu

    Joined:
    Jun 10, 2019
    Posts:
    14
    I am making a water system for my game... And for drowning to properly work, I need to reference a "health" variable and a death function from another script. The function was referenced successfully, but the variable is giving me this error.

    *Assets\Scripts\Player system\PlayerOxygen.cs(10,33): error CS0236: A field initializer cannot reference the non-static field, method, or property 'PlayerOxygen.data'*

    Code (CSharp):
    1.  using System.Collections;
    2.     using System.Collections.Generic;
    3.     using UnityEngine;
    4.     using UnityEngine.UI;
    5.     using UnityEngine.SceneManagement;
    6.     public class PlayerOxygen : MonoBehaviour
    7.     {
    8.         public PlayerDamage data;
    9.         public float playerHealth = data.health;
    10.         public float damage = 0.1f;
    11.         public float oxygen = 100f;
    12.         public Text O2Text;
    13.         public bool outOfO2 = false;
    14.         public bool underWater = false;
    15.         void Update(){
    16.             if (underWater == true) {
    17.                 oxygen = oxygen - 0.02f;
    18.             } else {
    19.                 oxygen++;
    20.             }
    21.             if (oxygen > 100f) {
    22.                 oxygen = 100f;
    23.             }
    24.             if (oxygen < 0f) {
    25.                 oxygen = 0f;
    26.             }
    27.             if (oxygen == 0f && underWater == true) {
    28.                 playerHealth = playerHealth - damage;
    29.             }
    30.             if (playerHealth == 0f) {
    31.                 data.Die();
    32.             }
    33.         }
    34.         public void OnTriggerEnter(Collision waterCollision) {
    35.             if (waterCollision.collider.tag=="Water"){
    36.                 underWater = true;
    37.             } else {
    38.                 underWater = false;
    39.             }
    40.         }
    41.     }
    Does anyone know how to fix this?
     
    Last edited: Feb 22, 2022
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,546
    So you know, you should use code-tags when posting code and not plain text. Also, the line number you show would be clear when doing so. Right now, we'd have to count lines. You can also edit your post above.

    EDIT: You already used this in a previous post. Why not now?

    That said, what's not clear about the error? Are you new to programming perhaps or have searched for this error and don't understand what it's saying? Which part is confusing? Do you want to know what a field is? A field initializer? The meaning of Static non-static?
     
    Bunny83 likes this.
  3. Jekirutu

    Jekirutu

    Joined:
    Jun 10, 2019
    Posts:
    14
    What I don't understand is what the error means. I have referenced variables from seperate scripts before, but here it doesn't work.

    When I remove "data.health" from line 9, there are no errors. I have checked the file name and namespace of the other script, so I don't believe that causes the issue...
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,546
    No, the part you don't understand is that you're not just "referenced variables from seperate scripts" but are doing it on a field initalizer and NOT in a method that's being called. This is initialized when the class it's in is created therefore that has limitations and it tells you the limitation in the error.

    You can't just assign one field at that point in time with the non-static contents of another field.

    Basically you can't do what you're trying to do. You'd need to do this in the "Start" or "Awake" method.
     
    Bunny83 likes this.
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,546
    Also, a little bit of advice here: Don't compare floats value with constant values like "playerHealth == 0f". It might be "0.00001" or something. For that I'd do if "< 0f" or use Mathf.Approximately.
     
    Jekirutu and Bunny83 like this.
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,539
    Just to settle the case. Have a look at this line:

    Code (CSharp):
    1. public float playerHealth = data.health;
    This is a field:

    Code (CSharp):
    1. public float playerHealth;
    and this is the field initializer:

    Code (CSharp):
    1.  = data.health;
    it is executed even before the constructor of the class is called when your class instance is created. So your "data" value can not possibly contain any meaningful data at this point. The compiler knows this and does not allow such an assignment inside a field initializer. You should remove the field initializer and move the initialization to Start or Awake.

    Code (CSharp):
    1. public float playerHealth;
    2. void Start()
    3. {
    4.     playerHealth = data.health;
    5. }
    6.  
    When Start is executed the whole class has already been created, initialized and the serialized data has been deserialized.

    Note that your whole oxygen logic is currently frame rate dependent. So on a faster PC you would loose ocxgen much faster. Also once you run out you would take damage much quicker. You should multiply your delta values by Time.deltaTime to make them time dependent (and framerate independent)

    Code (CSharp):
    1.             if (underWater == true) {
    2.                 oxygen = oxygen - 1f * Time.deltaTime;
    3.             } else {
    4.                 oxygen += 50f * Time.deltaTime;
    5.             }
    6.             if (oxygen > 100f) {
    7.                 oxygen = 100f;
    8.             }
    9.             if (oxygen < 0f) {
    10.                 oxygen = 0f;
    11.             }
    12.             if (oxygen == 0f && underWater == true) {
    13.                 playerHealth = playerHealth - damage * Time.deltaTime;
    14.             }
    15.             if (playerHealth <= 0f) {
    16.                 playerHealth = 0f;
    17.                 data.Die();
    18.             }
    Note I've adjusted your hardcoded values by a factor of about "50" so you should get roughly the same result as before assuming a framerate of about 50 - 60 fps. You have to adjust your "damage" value yourself. I would recommend besides the "damage" value to define an "oxygenDrain" and "oxygenRegen" field as well so that you can configure them in the inspector instead of the "1f" and "50f". When multiplied by deltaTime the meaning of the value changes. Instead of the "amount per frame" it becomes the "amount per second".

    So a "damage" value of 10 would take away 10 hp per second. At a framerate of 60 fps that would be about 0.1666 HP per frame. However at a framerate of 500fps it would only subtract 0.02HP per frame so that after 500 frames you have subtracted 10HP. Likewise if the framerate drops to 10fps (which we do not hope) it would subtract 1 HP per frame
     
    Jekirutu and MelvMay like this.
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,546
    Awesome. I guess someone has had their coffee today! :)