Skip to content

Commit cee23f1

Browse files
Merge branch 'develop' into pvp-fixes-develop-v2
2 parents 96cb8d8 + 56a2f20 commit cee23f1

File tree

10 files changed

+223
-26
lines changed

10 files changed

+223
-26
lines changed

.github/ISSUE_TEMPLATE/rfc-tracking-issue.md

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# This workflow manages issue assignments and related label changes:
2+
# 1. When someone is assigned to an issue:
3+
# - Removes "stat:awaiting-triage" label
4+
# - Adds "stat:Investigating" label
5+
# 2. When all assignees are removed from an issue:
6+
# - Adds "stat:awaiting-triage" label
7+
# - Removes "stat:Investigating" label
8+
# 3. When "stat:Investigating" label is added:
9+
# - Automatically assigns the issue to the person who added the label
10+
11+
name: Handle Issue Assignment and Labels
12+
13+
on:
14+
issues:
15+
types: [assigned, unassigned, labeled]
16+
17+
env:
18+
AWAITING-TRIAGE_LABEL: stat:awaiting-triage
19+
INVESTIGATING_LABEL: stat:Investigating
20+
21+
jobs:
22+
handle_assignment:
23+
name: Handle Issue Assignment Changes
24+
if: ${{ !github.event.issue.pull_request }} && ${{ github.event.issue.state == 'open' }}
25+
runs-on: ubuntu-latest
26+
permissions:
27+
issues: write
28+
29+
steps:
30+
- name: Handle Assignment Changes
31+
run: |
32+
if [[ "${{ github.event.action }}" == "assigned" ]]; then
33+
# Someone was assigned - remove awaiting-triage, add investigating
34+
echo "ADD=${{ env.INVESTIGATING_LABEL }}" >> $GITHUB_ENV
35+
echo "REMOVE=${{ env.AWAITING-TRIAGE_LABEL }}" >> $GITHUB_ENV
36+
elif [[ "${{ github.event.action }}" == "unassigned" ]]; then
37+
# Check if there are any remaining assignees
38+
ASSIGNEES=$(echo '${{ toJson(github.event.issue.assignees) }}' | jq length)
39+
if [[ "$ASSIGNEES" == "0" ]]; then
40+
# No assignees left - add awaiting-triage, remove investigating
41+
echo "ADD=${{ env.AWAITING-TRIAGE_LABEL }}" >> $GITHUB_ENV
42+
echo "REMOVE=${{ env.INVESTIGATING_LABEL }}" >> $GITHUB_ENV
43+
fi
44+
fi
45+
46+
- name: Update Labels
47+
if: env.ADD != '' || env.REMOVE != ''
48+
run: gh issue edit "$NUMBER" --add-label "$ADD" --remove-label "$REMOVE"
49+
env:
50+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51+
GH_REPO: ${{ github.repository }}
52+
NUMBER: ${{ github.event.issue.number }}
53+
54+
handle_investigating_label:
55+
name: Handle Investigating Label Addition
56+
if: ${{ github.event.action == 'labeled' && github.event.label.name == 'stat:Investigating' && !github.event.issue.pull_request && github.event.issue.state == 'open' }}
57+
runs-on: ubuntu-latest
58+
permissions:
59+
issues: write
60+
61+
steps:
62+
- name: Assign Issue to person that added Investigating Label
63+
run: |
64+
# Assign the issue to the person who added the label
65+
gh issue edit "$NUMBER" --add-assignee "$ACTOR"
66+
env:
67+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
68+
GH_REPO: ${{ github.repository }}
69+
NUMBER: ${{ github.event.issue.number }}
70+
ACTOR: ${{ github.actor }}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# This workflow will update issues with proper "conversation related" labels. This mean that stat:awaiting-repsonse label will be present after Unity account made comments and stat:reply-needed will be present when user made latest comment
2+
3+
name: Update conversation labels of the issue
4+
5+
# Trigger for the workflow
6+
# This trigger will populate the github.event object
7+
# Details on properties are here: https://docs.github.com/en/webhooks/webhook-events-and-payloads?actionType=created#issue_comment
8+
on:
9+
issue_comment:
10+
types: [created]
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.event.issue.number }}
14+
cancel-in-progress: true
15+
16+
# Define labels here
17+
env:
18+
AWAITING_RESPONSE: stat:awaiting-response
19+
REPLY_NEEDED: stat:reply-needed
20+
21+
jobs:
22+
conversation_labels:
23+
name: Calculate and update conversation labels of the issue
24+
if: ${{ !github.event.issue.pull_request && github.event.issue.state == 'open' }}
25+
runs-on: ubuntu-latest
26+
permissions:
27+
issues: write
28+
29+
steps:
30+
- name: Calculate labels
31+
run: |
32+
33+
if [[ "${{ github.event.comment.author_association }}" == "MEMBER" ]]; then
34+
# Unity member commented - add awaiting-response, remove reply-needed
35+
echo "ADD=${{ env.AWAITING_RESPONSE }}" >> $GITHUB_ENV
36+
echo "REMOVE=${{ env.REPLY_NEEDED }}" >> $GITHUB_ENV
37+
else
38+
# Non-Unity member commented - add reply-needed, remove awaiting-response
39+
echo "ADD=${{ env.REPLY_NEEDED }}" >> $GITHUB_ENV
40+
echo "REMOVE=${{ env.AWAITING_RESPONSE }}" >> $GITHUB_ENV
41+
fi
42+
43+
- name: Update labels
44+
# This runs a command using the github cli: https://cli.github.com/manual/gh_issue_edit
45+
# If $ADD is set, it will add the label, otherwise it will remove the label
46+
# There is no need to check if $ADD or $REMOVE is set, as the command will ignore it if it is empty
47+
run: gh issue edit "$NUMBER" --add-label "$ADD" --remove-label "$REMOVE"
48+
env:
49+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50+
GH_REPO: ${{ github.repository }}
51+
NUMBER: ${{ github.event.issue.number }}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# This workflow utilises an existing implementation (https://github.com/actions/stale) that performs the following actions:
2+
# 1) Adds "stale" label to issues that have "stat:awaiting-response" for more than 30 days meaning that since we don't have enough information we may potentially close such issue
3+
# 2) Closes issues that have been marked as "stale" for more than 30 days
4+
5+
# This affects only Issues but at some point we may also consider rules for PRs
6+
7+
name: Mark or Close Stale Issues
8+
9+
on:
10+
workflow_dispatch:
11+
schedule:
12+
- cron: '0 0 * * *' # Runs daily at midnight
13+
14+
jobs:
15+
stale:
16+
runs-on: ubuntu-latest
17+
permissions:
18+
issues: write
19+
20+
steps:
21+
- uses: actions/stale@v9
22+
with:
23+
# Only mark issues (not PRs) as stale
24+
any-of-labels: 'stat:awaiting-response'
25+
days-before-stale: 30
26+
days-before-close: 30
27+
stale-issue-label: 'Stale'
28+
exempt-issue-labels: 'stat:import,stat:imported'
29+
stale-issue-message: >
30+
This issue has been automatically marked as stale because it has been awaiting
31+
response for over 30 days without any activity.
32+
33+
Please update the issue with any new information or it may be closed in 30 days.
34+
close-issue-message: >
35+
This issue has been automatically closed because it has been stale for 30 days
36+
without any activity. Feel free to reopen if you have new information to add.
37+
# Prevent the action from marking/closing PRs
38+
days-before-pr-stale: -1
39+
days-before-pr-close: -1
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# This workflow will remove almost all labels from closed issues beside ones that could be relevant for future tracking like: "port:", "type:", "priority:", "regression" and "stat:imported"
2+
3+
name: Remove labels when issue is closed
4+
5+
on:
6+
issues:
7+
types: [closed] # We want it to run on closed issues
8+
9+
jobs:
10+
remove_labels:
11+
name: Calculate and remove issue labels
12+
if: ${{ !github.event.issue.pull_request }} # This is needed to distinguish from PRs (which we don't want to affect)
13+
runs-on: ubuntu-latest
14+
permissions:
15+
issues: write
16+
17+
steps:
18+
- name: Find labels to remove
19+
id: data
20+
run: |
21+
# Convert labels to array and filter out type: labels
22+
LABELS_TO_REMOVE=($(echo "$EXISTING_LABELS" | jq -r '.[] | select(startswith("type:") or startswith("port:") or startswith("priority:") or . == "regression" or . == "stat:imported" | not)'))
23+
24+
# Only proceed if we have labels to remove
25+
if [ ${#LABELS_TO_REMOVE[@]} -gt 0 ]; then
26+
echo "REMOVE_LABELS=$(IFS=,; echo "${LABELS_TO_REMOVE[*]}")" >> $GITHUB_ENV
27+
echo "HAS_LABELS=true" >> $GITHUB_ENV
28+
else
29+
echo "HAS_LABELS=false" >> $GITHUB_ENV
30+
fi
31+
env:
32+
EXISTING_LABELS: ${{ toJson(github.event.issue.labels.*.name) }}
33+
34+
- name: Remove labels
35+
if: ${{ env.REMOVE_LABELS != '' }}
36+
run: gh issue edit "$NUMBER" --remove-label "$REMOVE_LABELS"
37+
env:
38+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39+
GH_REPO: ${{ github.repository }}
40+
NUMBER: ${{ github.event.issue.number }}

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Additional documentation and release notes are available at [Multiplayer Documen
1616

1717
### Fixed
1818

19+
- Fixed issue where `NetworkAnimator` would log an error if there was no destination transition information. (#3384)
1920
- Fixed initial `NetworkTransform` spawn, ensure it uses world space. (#3361)
2021
- Fixed issue where `AnticipatedNetworkVariable` previous value returned by `AnticipatedNetworkVariable.OnAuthoritativeValueChanged` is updated correctly on the non-authoritative side. (#3322)
2122

com.unity.netcode.gameobjects/Components/NetworkAnimator.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,10 +1226,11 @@ internal void UpdateAnimationState(AnimationState animationState)
12261226
NetworkLog.LogError($"[DestinationState To Transition Info] Layer ({animationState.Layer}) sub-table does not contain destination state ({animationState.DestinationStateHash})!");
12271227
}
12281228
}
1229-
else if (NetworkManager.LogLevel == LogLevel.Developer)
1230-
{
1231-
NetworkLog.LogError($"[DestinationState To Transition Info] Layer ({animationState.Layer}) does not exist!");
1232-
}
1229+
// For reference, it is valid to have no transition information
1230+
//else if (NetworkManager.LogLevel == LogLevel.Developer)
1231+
//{
1232+
// NetworkLog.LogError($"[DestinationState To Transition Info] Layer ({animationState.Layer}) does not exist!");
1233+
//}
12331234
}
12341235
else if (animationState.Transition && animationState.CrossFade)
12351236
{

com.unity.netcode.gameobjects/Runtime/Timing/NetworkTime.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public struct NetworkTime
5050
/// </summary>
5151
public float FixedDeltaTime => (float)m_TickInterval;
5252

53+
/// <summary>
54+
/// Gets the fixed delta time as a double. This value is calculated by dividing 1.0 by the <see cref="TickRate"/> and stays constant.
55+
/// </summary>
56+
public double FixedDeltaTimeAsDouble => m_TickInterval;
57+
5358
/// <summary>
5459
/// Gets the amount of network ticks which have passed until reaching the current time value.
5560
/// </summary>

com.unity.netcode.gameobjects/Tests/Runtime/Timing/NetworkTimeSystemTests.cs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,35 +62,34 @@ public IEnumerator PlayerLoopTimeTest_WithDifferentTimeScale([Values(0.0f, 0.1f,
6262
public IEnumerator CorrectAmountTicksTest()
6363
{
6464
NetworkTickSystem tickSystem = NetworkManager.Singleton.NetworkTickSystem;
65-
float delta = tickSystem.LocalTime.FixedDeltaTime;
65+
double delta = tickSystem.LocalTime.FixedDeltaTimeAsDouble;
6666
int previous_localTickCalculated = 0;
6767
int previous_serverTickCalculated = 0;
6868

6969
while (tickSystem.LocalTime.Time < 3f)
7070
{
7171
yield return null;
7272

73-
var tickCalculated = tickSystem.LocalTime.Time / delta;
74-
previous_localTickCalculated = (int)tickCalculated;
73+
var localTickCalculated = tickSystem.LocalTime.Time / delta;
74+
previous_localTickCalculated = (int)localTickCalculated;
7575

7676
// This check is needed due to double division imprecision of large numbers
77-
if ((tickCalculated - previous_localTickCalculated) >= 0.999999999999)
77+
if ((localTickCalculated - previous_localTickCalculated) >= 0.999999999999)
7878
{
7979
previous_localTickCalculated++;
8080
}
8181

82-
83-
tickCalculated = NetworkManager.Singleton.ServerTime.Time / delta;
84-
previous_serverTickCalculated = (int)tickCalculated;
82+
var serverTickCalculated = tickSystem.ServerTime.Time / delta;
83+
previous_serverTickCalculated = (int)serverTickCalculated;
8584

8685
// This check is needed due to double division imprecision of large numbers
87-
if ((tickCalculated - previous_serverTickCalculated) >= 0.999999999999)
86+
if ((serverTickCalculated - previous_serverTickCalculated) >= 0.999999999999)
8887
{
8988
previous_serverTickCalculated++;
9089
}
9190

92-
Assert.AreEqual(previous_localTickCalculated, NetworkManager.Singleton.LocalTime.Tick, $"Calculated local tick {previous_localTickCalculated} does not match local tick {NetworkManager.Singleton.LocalTime.Tick}!");
93-
Assert.AreEqual(previous_serverTickCalculated, NetworkManager.Singleton.ServerTime.Tick, $"Calculated server tick {previous_serverTickCalculated} does not match server tick {NetworkManager.Singleton.ServerTime.Tick}!");
91+
Assert.AreEqual(previous_localTickCalculated, NetworkManager.Singleton.LocalTime.Tick, $"Calculated local tick {previous_localTickCalculated} does not match local tick {NetworkManager.Singleton.LocalTime.Tick}!]n Local Tick-Calc: {localTickCalculated} LocalTime: {tickSystem.LocalTime.Time} | Server Tick-Calc: {serverTickCalculated} ServerTime: {tickSystem.ServerTime.Time} | TickDelta: {delta}");
92+
Assert.AreEqual(previous_serverTickCalculated, NetworkManager.Singleton.ServerTime.Tick, $"Calculated server tick {previous_serverTickCalculated} does not match server tick {NetworkManager.Singleton.ServerTime.Tick}!\n Local Tick-Calc: {localTickCalculated} LocalTime: {tickSystem.LocalTime.Time} | Server Tick-Calc: {serverTickCalculated} ServerTime: {tickSystem.ServerTime.Time} | TickDelta: {delta}");
9493
Assert.AreEqual((float)NetworkManager.Singleton.LocalTime.Time, (float)NetworkManager.Singleton.ServerTime.Time, $"Local time {(float)NetworkManager.Singleton.LocalTime.Time} is not approximately server time {(float)NetworkManager.Singleton.ServerTime.Time}!", FloatComparer.s_ComparerWithDefaultTolerance);
9594
}
9695
}

com.unity.netcode.gameobjects/Tests/Runtime/Timing/TimeInitializationTest.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ public IEnumerator TestClientTimeInitializationOnConnect([Values(0, 1f)] float s
4343
yield return new WaitUntil(() => server.NetworkTickSystem.ServerTime.Tick > 2);
4444

4545
var serverTimePassed = server.NetworkTickSystem.ServerTime.Time;
46-
var expectedServerTickCount = Mathf.FloorToInt((float)(serverTimePassed * 30));
4746

47+
// Use FixedDeltaTimeAsDouble and divide the tick frequency into the time passed to get the accurate tick count
48+
var expectedServerTickCount = (int)System.Math.Floor(serverTimePassed / server.ServerTime.FixedDeltaTimeAsDouble);
4849
var ticksPassed = server.NetworkTickSystem.ServerTime.Tick - serverTick;
49-
Assert.AreEqual(expectedServerTickCount, ticksPassed);
50+
Assert.AreEqual(expectedServerTickCount, ticksPassed, $"Calculated tick failed: Tick ({expectedServerTickCount}) TicksPassed ({ticksPassed}) Server Tick ({server.NetworkTickSystem.ServerTime.Tick}) Prev-Server Tick ({serverTick})");
5051

5152
yield return new WaitForSeconds(clientStartDelay);
5253

0 commit comments

Comments
 (0)