{"record":{"id":"a1e04265e76e0c54","repo":"stride3d/stride","slug":"direction-is-in-neutral-position","errorCode":null,"errorMessage":"Direction is in neutral position","messagePattern":"Direction is in neutral position","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Input/Direction.cs","lineNumber":64,"sourceCode":"        /// with 0/1 corresponding to the direction (0,1), 1/4 corresponding to (1,0), etc.\n        /// </summary>\n        /// <param name=\"value\">The amount of ticks clockwise from the Up direction (numerator)</param>\n        /// <param name=\"maxValue\">The number of ticks representing a full rotation (denominator)</param>\n        /// <returns>A direction with ratio <paramref name=\"value\"/> over <paramref name=\"maxValue\"/></returns>\n        public static Direction FromTicks(int value, int maxValue)\n        {\n            return new Direction((int)(MaxValue / maxValue * value));\n        }\n\n        /// <summary>\n        /// Retrieves the amount of ticks clockwise from the Up direction\n        /// </summary>\n        /// <param name=\"maxValue\">The number of ticks representing a full rotation</param>\n        /// <returns></returns>\n        public int GetTicks(int maxValue)\n        {\n            if (!value.HasValue)\n                throw new InvalidOperationException(\"Direction is in neutral position\");\n            if (maxValue <= 0)\n                throw new ArgumentOutOfRangeException(nameof(maxValue));\n            \n            return (int)Math.Round(value.Value / ((double)MaxValue / (uint)maxValue)) % maxValue;\n        }\n\n        public static explicit operator Vector2(Direction value)\n        {\n            if (!value.value.HasValue)\n                return Vector2.Zero;\n\n            return new Vector2\n            {\n                X = (float)Math.Sin(value.value.Value * FullAngleInverse),\n                Y = (float)Math.Cos(value.value.Value * FullAngleInverse),\n            };\n        }\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Input/Direction.cs#L46-L82","documentation":"Direction.GetTicks converts the current direction into ticks on a circular scale. If the underlying value is null — the direction is in its neutral/rest position with no deflection — it throws InvalidOperationException because there is no rotation to convert.","triggerScenarios":"Calling GetTicks on a Direction instance whose backing value has not been set (e.g. a gamepad stick or trigger at rest, or a Direction created but never updated) before reading tick values.","commonSituations":"Polling a gamepad's virtual 'Direction' property on the first frame before any input event; reading rotation ticks for a device returning neutral position (stick centered).","solutions":["Check whether the direction has a value before calling GetTicks (e.g. inspect HasValue/neutral state)","Skip tick computation when the input is neutral and treat it as 0 in caller logic","Use the gamepad's axis/index values instead when neutral readings matter"],"exampleFix":"// before\nint ticks = direction.GetTicks(maxValue);\n// after\nint ticks = direction.HasValue ? direction.GetTicks(maxValue) : 0;","handlingStrategy":"validation","validationCode":"if (!direction.HasValue) return 0;\nint ticks = direction.GetTicks(maxValue);","typeGuard":"bool IsActive(Direction d) => d.HasValue;","tryCatchPattern":"try { ticks = direction.GetTicks(maxValue); }\ncatch (InvalidOperationException) { ticks = 0; }","preventionTips":["Treat neutral position as 0 ticks in input aggregation","Check input state before first use each frame","Cache whether the device has ever reported a non-neutral value"],"tags":["input","gestures","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}