Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Reward system suggestion

Discussion in 'Game Foundation' started by RaadAldalaq, Feb 17, 2021.

  1. RaadAldalaq

    RaadAldalaq

    Joined:
    Sep 29, 2016
    Posts:
    4
    Hello,

    I'm currently doing a deep dive into the GameFoundation package and I noticed something that is a bit inflexible in terms of your reward implementation. The fact that you can't set your time, you're currently using
    Code (CSharp):
    1. DateTime.UtcNow
    to get the current time, but a lot of cases will have the user needing to use their own time provider, it could be server time etc... a suggestion maybe allow us to inject a time provider for the GameFoundation package? or a time provider per module? could be a simple
    Code (CSharp):
    1. func<DateTime> TimeGetter
    or something similar using interfaces.
     
    richj_unity and erika_d like this.
  2. richj_unity

    richj_unity

    Unity Technologies

    Joined:
    Sep 23, 2019
    Posts:
    40
    An injectable time provider is something we intend to add (though I couldn't say when). Thanks for the feedback!
     
    erika_d likes this.
  3. Sukender_OB

    Sukender_OB

    Joined:
    Nov 14, 2019
    Posts:
    18
    @RaadAldalaq

    Rewards indeed may use "Internet time" to avoid cheating by adjusting system clock. So yes, I feel like the proposal is nice.

    Just to add more, I recently added a basic "Internet UTC time" class (for another purpose) which might be of some use. It uses an asynchronous C# web request (not a Unity coroutine) to a common web service. It doesn't compensate ping, and doesn't detect clock change between synchronizations (but you may add it). Feel free to use and enhance it (let's say the licence is WTFPL).

    Code (CSharp):
    1. public class CheckedUTCTime {
    2.     public CheckedUTCTime() { Synchronize(); }
    3.  
    4.     /// Offset from local time to checked (Internet) time.
    5.     TimeSpan? offset = null;
    6.  
    7.     public bool IsReady() { return offset.HasValue; }
    8.  
    9.     class WorldtimeApiJson {
    10. #pragma warning disable CS0649
    11.         public string utc_offset;
    12.         // ... <= Other members here, removed to let this code snippet short enough.
    13. #pragma warning restore CS0649
    14.     }
    15.  
    16.     /// Restarts a time synchronization.
    17.     /// During the asynchronous process, previous time will be used.
    18.     public void Synchronize() {
    19.         // Uses worldtimeapi.org, but should be extended to switch to other sources.
    20.         // Note: worldclockapi.com doesn't give seconds. We may use local time seconds.
    21.         Task.Run(() => {
    22.             try {
    23.                 const string SERVICE_URL = "http://worldtimeapi.org/api/timezone/Etc/UTC";
    24.                 var request = (HttpWebRequest)WebRequest.Create(SERVICE_URL);
    25.                 using var response = (HttpWebResponse)request.GetResponse();
    26.                 using var receiveStream = response.GetResponseStream();
    27.                 using var readStream = new StreamReader(receiveStream, Encoding.UTF8);
    28.                 var json = readStream.ReadToEnd();
    29.                 var data = UnityEngine.JsonUtility.FromJson<WorldtimeApiJson>(json);
    30.                 // Note: worldtimeapi.org uses 6 decimal digits, and +00:00 instead of Z
    31.                 var internetTime = DateTime.ParseExact(data.utc_datetime.Replace("+00:00", "0Z"), "o", null, System.Globalization.DateTimeStyles.RoundtripKind);
    32.                 offset = internetTime - DateTime.UtcNow;
    33.             } catch (Exception e) {
    34.                 UnityEngine.Debug.LogException(e);
    35.                 offset = null;
    36.             }
    37.         });
    38.     }
    39.  
    40.     /// Gives an UTC time which is internet-checked.
    41.     ///\sa IsReady()
    42.     public DateTime UtcNow(DateTime defaultValue) {
    43.         if (!offset.HasValue) {
    44.             return defaultValue;
    45.             //or throw WhateverExceptionYoyWant("Time is not synchronized.");
    46.         }
    47.         return DateTime.UtcNow + offset.Value;
    48.     }
    49. }
     
    erika_d likes this.